perm filename CLCOMP.MSG[COM,LSP]6 blob sn#859384 filedate 1988-07-08 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002
C00003 ENDMK
C⊗;
∂29-Mar-88  2234	CL-Compiler-mailer 	Eval-When -- a radical view   
Received: from labrea.Stanford.EDU by SAIL.Stanford.EDU with TCP; 29 Mar 88  22:34:24 PST
Received: by labrea.Stanford.EDU; Tue, 29 Mar 88 22:32:17 PST
Received: from bhopal.lucid.com by edsel id AA12080g; Tue, 29 Mar 88 22:24:31 PST
Received: by bhopal id AA01977g; Tue, 29 Mar 88 22:24:41 PST
Date: Tue, 29 Mar 88 22:24:41 PST
From: Jon L White <edsel!jonl@labrea.Stanford.EDU>
Message-Id: <8803300624.AA01977@bhopal.lucid.com>
To: Rob.MacLachlan@wb1.cs.cmu.edu
Cc: sandra@cs.utah.edu, cl-compiler@sail.stanford.edu
In-Reply-To: Rob.MacLachlan@WB1.CS.CMU.EDU's message of Sat, 26 Mar 88 12:38:29 EST <8803270744.AA29754@edsel.lucid.com>
Subject: Eval-When -- a radical view 

You sure put "a mouthful" in your reply!  I'm not sure that I'll be able now
to comment on all the things you've brought up, but here goes ...

re: A narrow complaint that I have is that it seems you haven't been as 
    consistent as you could be in extending the semantics described in CLTL.  
    In your version, compiling:
    (eval-when (compile)
      (eval-when (load)
	(print 'foo)))
    . . . 

You're quite right; the code I suggested for EVAL-WHEN should have the line:
	(:eval-before-compile  T)
changed to be
	(:eval-before-compile  (or (memq 'eval situations)
                                   (memq 'load situations)))
That should better reflect the semantics of what CLtL calls "compile-time-too".


re: It should also be clear that using a dynamic variable *EVAL-WHEN-STATE* is
    an implementation detail, and not part of the inherent semantics.  For one,
    requiring EVAL to bind a special prevents it from being tail-recursive.  
    What you really want to do is lexically modify the evaluation rules.  Using
    a dynamic variable bound by EVAL and COMPILE is an approximation of this, 
    but things become more confusing when there are any other ways for the 
    lexical environment to become null.  

Right again.  Mostly my use of the dynamic variable *EVAL-WHEN-STATE* is 
merely to make it easier to understand a rather simple defmacro definition 
for EVAL-WHEN.


re: Even supposing we could clearly define EVAL-WHEN in a way that extended 
    cleanly across all implementations that we want to support, EVAL-WHEN 
    would still be bad because it is too powerful: it allows users to say 
    things that aren't meaningful across all implementations -- it encourages 
    writing of programs that don't work interpreted (or compiled).

This paragraph is representative of large section of your note, basically
saying that trying to "patch up" EVAL-WHEN is a doomed process.  I disagree
mildly.  In particular, the ability to "say things that aren't meaningful"
is not focused enough to warrant tossing out eval-when.  I agree that the
willy-nilly generation of legal syntatic forms will come up with some
meaningless phrases; why, even my proposal presented an interpretation for

   (defun foo (x) 
     (mumble (eval-when (load) (bletch x))))

even though that is clearly a meaningless thing to do. [my presentation was
to view the 'load' situation as meaning that this should be incorporated
into the compiled code and only into the compiled code; Sandra's presentation
 -- at least verbally at the Friday morning meetings -- was that it could
mean something like #,  and in a way I prefer hers now]  Rather, I like the 
simplicity of EVAL-WHEN for the combinations that do make good sense.  As
you say, 

    I searched through our system sources looking for all uses of EVAL-WHEN. 
    Nearly all uses involved one of two situations lists:
     (COMPILE LOAD EVAL)
     (COMPILE EVAL)
    . . . 
    There were also quite a few uses of the (COMPILE) situation list, but 
    nearly all of these were erroneous; the code wouldn't have worked 
    interpreted.  

On the other hand, in our system, the relatively few instances of the (COMPILE)
situation are precisely for code that can't work interpreted.  I myself have
even inserted a couple of lines like
    (eval-when (eval) 
      (error "You Loser! this file can't be run interpretively"))
We have a few places in our system that are defined only by the code-generator
parts of the compiler; some of these functions have interpreter entries that
look like the classic:
    (defun car (x)
      (check-type x list)
      (car x))
but most are merely internal compiler stuff that doesn't need such an entry.
Files that reference such functions simply can't be run except when compiled.

But the whole point is that whether the number of "meaningful" situations
is 3 or 4 or 5 out of a possible 8, that is no reason to give up just
because the other few are not particularly useful.


Now, Sandra brings up another good point (which you too, Rob, mention) --

    The problem of having the same piece of code sometimes get evaluated in
    the current lexical environment and sometimes not is going to be easy to
    resolve.  There does not seem to be much disagreement that the COMPILE
    situation must do its evaluation in the null lexical environment. . . . 

Maybe I'll exercise my perogative to bring in some "disagreement".  Perhaps 
feeding an &environment argument to eval-when isn't so bad after all.  In 
terms of my trial-baloon defmacro for eval-when, the only problematical point
is how to transmit an outter environment down through the code:
        (mapc #'eval-internal code)
I'm sure that some suitable solution could be found.  Maybe even binding
the *EVAL-WHEN-STATE* to it instead of :EVAL-BEFORE-COMPILE could work?
Also Sandra's mention of a possible definition of DEFMACRO in terms of
EVAL-WHEN and SETF(MACRO-FUNCTION ...) adds weight to the need for a solution.
At any rate, I think this is indeed an important enough problem to spend
some time thinking about [looking for a consistent solution that is, not
just looking for reasons to chuck out the whole kit-and-kaboodle].


If we were to adopt some notion that each "file" is a lexical entity --  
equivalent for scoping as if there were a giant (locally ....) enclosing the 
entire file -- then it would be even more important to pass in &environment
information to eval-when.  [But of course you couldn't do this "enclosing"
literally since that would mean reading in all the forms of the file before 
processing any of them].  My proposal for a lexical-file-proclaim needs
such a notion of lexical scoping, and I believe it accurately reflects
desiderata set out by Beckerele and others about the semantics of what
a "file" is such that you can apply COMPILE-FILE to it; but this is a
topic for yet another time.


Incidentally, the example that Sandra offers

    (eval-when (eval compile load)
	(let ((x  (compute-some-value)))
	    (defmacro foo (y)
		`(+ ,x ,y))))

Could just as well have been

    (eval-when (eval compile)
	(let ((x  (compute-some-value)))
	    (defmacro foo (y)
		`(+ ,x ,y))))


That is, the proponents of this style frequently need it only in the
compiler's environment.  For an implementation that doesn't have an
interpreter, then the situation marker (eval compile) is still right,
since it means first compiling
	(let ((x  (compute-some-value)))
	    (defmacro foo (y)
		`(+ ,x ,y)))
and then immediately afterwards calling that compiled "thunk" to be executed.
The macro is now "alive" for subsequent compilations of forms found later in
the file.


-- JonL --

∂29-Mar-88  2236	CL-Compiler-mailer 	Eval-When -- a radical view   
Received: from labrea.Stanford.EDU by SAIL.Stanford.EDU with TCP; 29 Mar 88  22:36:03 PST
Received: by labrea.Stanford.EDU; Tue, 29 Mar 88 22:34:23 PST
Received: from bhopal.lucid.com by edsel id AA12136g; Tue, 29 Mar 88 22:31:34 PST
Received: by bhopal id AA01993g; Tue, 29 Mar 88 22:31:44 PST
Date: Tue, 29 Mar 88 22:31:44 PST
From: Jon L White <edsel!jonl@labrea.Stanford.EDU>
Message-Id: <8803300631.AA01993@bhopal.lucid.com>
To: jeff%aiva.edinburgh.ac.uk@nss.cs.ucl.ac.uk
Cc: cl-compiler@sail.stanford.edu, <@edsel,@labrea.stanford.edu:jonl>
In-Reply-To: Jeff Dalton's message of Mon, 28 Mar 88 17:00:29 bst <22121.8803281600@aiva.ed.ac.uk>
Subject: Eval-When -- a radical view

re: There is one subtlety that I think should be addressed, and that is:
    what should implementations that always and only compile do?  . . . 

So maybe the top-level processor that is masquarading as "top-level EVAL"
should call a private entry into the compiler that doesn't rebind
*EVAL-WHEN-STATE*?  I already had to presume such an entry to the
interpreter in the trial-balloon defmacro for EVAL-WHEN.

Even in the most minimal of implementations, I presume that LOAD differs
from COMPILE-FILE in that LOAD will successively "execute" each form 
before even reading the next one.  And COMPILE-FILE is called primarily
for the side-effect of creating a "binary" file.   So it still makes sense 
to me to have separate "situation" markers for :EVALUATING and :COMPILING,
even though serious portability questions arise about some combinations
of "situations".



-- JonL --

∂30-Mar-88  1055	CL-Compiler-mailer 	Eval-When -- a radical view   
Received: from XX.LCS.MIT.EDU by SAIL.Stanford.EDU with TCP; 30 Mar 88  10:53:00 PST
Received: from LIVE-OAK.LCS.MIT.EDU by XX.LCS.MIT.EDU via Chaosnet; 30 Mar 88 11:00-EST
Received: from ACORN.Gold-Hill.DialNet.Symbolics.COM by MIT-LIVE-OAK.DialNet.Symbolics.COM via DIAL with SMTP id 85774; 30 Mar 88 10:11:55-EST
Received: from BOSTON.Gold-Hill.DialNet.Symbolics.COM by ACORN.Gold-Hill.DialNet.Symbolics.COM via CHAOS with CHAOS-MAIL id 97736; Wed 30-Mar-88 09:13:24-EST
Date: Wed, 30 Mar 88 09:15 est
From: mike%acorn@oak.lcs.mit.edu (mike@gold-hill.com after 1-April-88)
COMMENTS: NOTE %acorn@oak... CHANGES TO @GOLD-HILL.COM ON 1-April-88
To: edsel!jonl@labrea.Stanford.EDU
Subject: Eval-When -- a radical view 
Cc: Rob.MacLachlan@wb1.cs.cmu.edu, sandra@cs.utah.edu,
    cl-compiler@sail.stanford.edu

    
        I searched through our system sources looking for all uses of 
        EVAL-WHEN. 
        Nearly all uses involved one of two situations lists:
         (COMPILE LOAD EVAL)
         (COMPILE EVAL)

In our implementation, the most common situation for eval-when is
(compile eval). This is used to exclude macros, constants, etc that
are compiled in to a delivered system. Another common one is
(load eval), which is used within expansions of macros to force loading
of runtime support: e.g.,

  (defmacro mac (....)
   `(progn
      (eval-when (load eval) (require "runtime-support"))
      ...rest of expansion here....))

This is nice because in the file header you only have to require the
module that defines the macros, via: 
(eval-when (compile eval) (require "the-macros")) You don't have to
know where the runtime support lives, or use autoloading or anything.

There are almost no uses of (compile eval load) anywhere.

I am of the opinion that we should define what EVAL-WHEN does, and
not chuck it out in favor of new constructs, like EVAL-EARLY, etc.


...mike beckerle

∂12-Apr-88  1347	CL-Compiler-mailer 	archives  
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 12 Apr 88  13:47:25 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA26559; Tue, 12 Apr 88 14:47:52 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8804122047.AA26559@cs.utah.edu>
Date: Tue, 12 Apr 88 14:47:49 MDT
Subject: archives
To: cl-compiler@sail.stanford.edu

Mail sent to cl-compiler is now being archived on cs.utah.edu, in the
file /v/tmp/spool/mail/cl-compiler.  If this file grows too humungous
I'll try to split it up into smaller pieces from time to time.

-Sandra
-------

∂06-May-88  1358	CL-Compiler-mailer 	nesting of EVAL-WHENs    
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 6 May 88  13:58:06 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA26103; Fri, 6 May 88 14:58:39 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805062058.AA26103@cs.utah.edu>
Date: Fri, 6 May 88 14:58:37 MDT
Subject: nesting of EVAL-WHENs
To: cl-compiler@sail.stanford.edu

I've been trying to write up some formal proposals to firm up what we
now seem to think is the "right" way to handle defining macros and
eval-when, and I've run into a problem with the semantics of nested
EVAL-WHENs.

From our Palo Alto meeting, there seemed to be some consensus that the
following kind of code should "work":

(eval-when (eval compile load)
    (let ((x  (some-hairy-computation)))
        (defmacro foo (y)
            `(+ ,x ,y))))

Namely, the macro function FOO should be closed over X, and since the value
of X is available at compile time everything should be hunky-dory.

According to our model of how the compiler treats top-level forms,
the defmacro itself expands into another eval-when, something like

(eval-when (eval compile load)
    (let ((x  (some-hairy-computation)))
        (eval-when (eval compile load)
            (setf (macro-function 'foo)
                #'(lambda (form env)
                      (let ((y  (second form)))
                          `(+ ,x ,y))))
	    'foo)))

So, here's the problem.  As I understand our latest spec on how
EVAL-WHEN works, the compiler will first evaluate the entire LET form
that binds X in the null lexical environment, and FOO will get the
"right" macro definition as a function closed over X.  Then, the
compiler will do the processing for the LOAD part of the EVAL-WHEN.  In
doing so, it will hit that nested EVAL-WHEN, see that COMPILE is
specified among the situations, and promptly redefine the macro
definition of FOO as a function in the null lexical environment which
is not closed over X.  Which isn't what we wanted to happen.

I thought of maybe saying that LOAD or EVAL processing of the body of
the EVAL-WHEN disables COMPILE processing of nested EVAL-WHENs in
the body.  This would be incompatible with the current behavior as
specified in CLtL, however, and I'm not sure that it would be generally
the right thing to do in other situations.  Alternatively, we could keep
the current restriction on macro functions always being defined in the
null lexical environment, but that would be difficult to explain using
our model of how defining macros work.

Anybody else have thoughts on this?

-Sandra
-------

∂07-May-88  0456	CL-Compiler-mailer 	nesting of EVAL-WHENs    
Received: from labrea.stanford.edu by SAIL.Stanford.EDU with TCP; 7 May 88  04:55:55 PDT
Received: by labrea.stanford.edu; Sat, 7 May 88 04:56:02 PDT
Received: from bhopal.lucid.com by edsel id AA13890g; Sat, 7 May 88 02:13:52 PDT
Received: by bhopal id AA05540g; Sat, 7 May 88 02:16:36 PDT
Date: Sat, 7 May 88 02:16:36 PDT
From: Jon L White <edsel!jonl@labrea.stanford.edu>
Message-Id: <8805070916.AA05540@bhopal.lucid.com>
To: sandra@cs.utah.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Sandra J Loosemore's message of Fri, 6 May 88 14:58:37 MDT <8805062058.AA26103@cs.utah.edu>
Subject: nesting of EVAL-WHENs

I'm going to need some more time to think about this question, but vaguely
I thought the model of eval-when processing tried to make sure that subforms
only got evaluated once when there were multiple applicable situations.
For the interior eval-when(eval compile load), the first evaluation during 
compilation is because of the EVAL situation in the outter eval-when; then
the second "potential" evaluation is during the compilation of the inner
eval-when, when it notices that it has the 'compile' situaiton.  Clearly
we need to insure that the eval-when model has a state that says:
   "compiling, but have already eval'd this"

-- JonL --

∂08-May-88  1246	CL-Compiler-mailer 	Re: nesting of EVAL-WHENs
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 8 May 88  12:45:57 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA03719; Sun, 8 May 88 12:37:57 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805081837.AA03719@cs.utah.edu>
Date: Sun, 8 May 88 12:37:54 MDT
Subject: Re: nesting of EVAL-WHENs
To: Jon L White <edsel!jonl@labrea.stanford.edu>
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Jon L White <edsel!jonl@labrea.stanford.edu>, Sat, 7 May 88 02:16:36 PDT

Hmmm.  I suppose we could say that if both COMPILE and LOAD are
specified in the outer EVAL-WHEN, when the compiler is processing the
body to spit out the code to do the LOAD evaluation, it should not do
any more compile-time evaluation of nested subforms.  This could be
modeled with our view of how EVAL-WHEN might be implemented as a macro
by having (EVAL-WHEN (COMPILE LOAD) ...) expand into a MACROLET, that
shadows EVAL-WHEN with a new definition which totally ignores the
COMPILE situation.

-Sandra
-------

∂09-May-88  0852	CL-Compiler-mailer 	proposals 
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 9 May 88  08:52:42 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA22751; Mon, 9 May 88 09:53:17 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805091553.AA22751@cs.utah.edu>
Date: Mon, 9 May 88 09:53:16 MDT
Subject: proposals
To: cl-compiler@sail.stanford.edu

You should be getting three proposals from me immediately following this
message.  I would like to get these proposals (or some modified version
of them) distributed to the full X3J13 committee at the June meeting, so
that they could be voted on at the meeting after that.  (It is probably
too late to hope for getting them up for a vote at the June meeting.)

So, please read them over.  All of the proposals could use more work on
the "current practice" and "cost to implementors" sections, so if you
vendors out there want to get your names mentioned :-), send mail.
I will put together revised versions to incorporate comments/complaints.

-Sandra
-------

∂09-May-88  0854	CL-Compiler-mailer 	issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS    
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 9 May 88  08:53:57 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA22789; Mon, 9 May 88 09:54:36 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805091554.AA22789@cs.utah.edu>
Date: Mon, 9 May 88 09:54:35 MDT
Subject: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS
To: cl-compiler@sail.stanford.edu


Issue:		COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS
References:	CLtL pages 66-70, 143
Category:	CLARIFICATION
Edit history:   V1, 07 Oct 1987 Sandra Loosemore
                V2, 15 Oct 1987 Sandra Loosemore
                V3, 15 Jan 1988 Sandra Loosemore
		V4, 06 May 1988 Sandra Loosemore



Problem Description:

Standard programming practices assume that, when calls to defining
macros such as DEFMACRO and DEFVAR are compiled, certain side-effects
occur that affect how the compiler processes subsequent forms.
However, these side-effects are not mentioned in CLtL, except for a
passing mention that macro definitions must be ``seen'' by the
compiler before it can compile calls to those macros correctly. 


Proposal: COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY

(1) Certain defining macros, appearing within a file being processed
by COMPILE-FILE, normally have compile-time side effects which affect
how subsequent forms in the same file are compiled.  The defining macros
and their specific side effects are as follows:
 
DEFTYPE:   Type names defined via DEFTYPE must be recognized as valid in
subsequent type declarations.
 
DEFMACRO, DEFINE-MODIFY-MACRO:  Macro definitions must be stored at compile
time, so that occurences of the macro later on in the file will be expanded
correctly.  The body of the macro (but not necesarily its expansion) must 
be evaluable at compile time.
 
DEFUN:  An implementation may choose to store information about the
function for the purposes of compile-time error-checking (such as checking
the number of arguments on calls).  Portable code should not rely on DEFUN
making the function definition available at compile time.
 
DEFVAR, DEFPARAMETER:  The compiler must recognize that the variables
named by these forms have been proclaimed special.  The initial value form
must not be evaluated at compile time.
 
DEFCONSTANT:  An implementation may choose to store information about the
variable for the purposes of compile-time error-checking (such as checking
for rebinding of or assignment to the variable).  If the initial value form
is a constant, an implementation may also choose to evaluate it at compile 
time for the purposes of constant-folding.
 
DEFSETF, DEFINE-SETF-METHOD:  SETF methods must be available during the
expansion of calls to SETF later on in the file.  The body of
DEFINE-SETF-METHOD and the complex form of DEFSETF must be evaluable at
compile time.
 
DEFSTRUCT:  The structure type name must be recognized as a valid type name
in declarations, as for DEFTYPE.  The structure slot accessors must be made
known to SETF.  In addition, further DEFSTRUCT definitions should be able
to :INCLUDE a structure type defined earlier in the file being compiled.
The functions which DEFSTRUCT generates, and the #S reader syntax, may or
may not be available at compile time.

(2) A model which explains how these compile-time side-effects happen is
that each defining macro expands into one or more EVAL-WHEN forms.  The
bodies of the EVAL-WHEN forms contain code which causes the appropriate
information to be stored.  Different information may be stored at
compile-time than when the defining macros are processed interpretively
or when the compiled file is loaded.

(3) The information stored by the defining macros at compile time may
or may not be available to the interpreter (either during or after
compilation), or during subsequent calls to COMPILE or COMPILE-FILE.
For example, the following code is nonportable because it assumes that the
compiler stores the macro definition of FOO where it is available to the
interpreter:

    (defmacro foo (x) `(car ,x))
    (eval-when (eval compile load)
        (print (foo '(a b c))))

A portable way to do the same thing would be to include the macro definition
inside the EVAL-WHEN:

    (eval-when (eval compile load)
        (defmacro foo (x) `(car ,x))
        (print (foo '(a b c))))



Rationale:

The proposal reflects standard programming practices.  The primary purpose
of the proposal is to make an explicit statement that CL supports the
behavior that most programmers expect and many implementations already
provide.


Current Practice:

Many (probably most) Common Lisp implementations, including VaxLisp and
Lucid Lisp, are already largely in conformance.  
 
Kyoto Common Lisp is a notable offender.  By default, KCL evaluates *all*
top level forms as they are compiled, which is clearly in violation of the
behavior specified on p 69-70 of CLtL.  There is a flag to disable the
compile-time evaluation, but then macros such as DEFMACRO, DEFVAR, etc. do
not make their definitions available at compile-time either.


Cost to implementors:

Making the defining macros expand into EVAL-WHENs to store the required
information is a simple and recommended implementation technique.


Cost to users:

Since CLtL does not specify whether and what compile-time side-effects
happen, any user code which relies on them is, strictly speaking,
nonportable.  In practice, however, most programmers already expect
the behavior described in this proposal and will not find it to be
an incompatible change.


Benefits:

Adoption of the proposal will provide more definite guidelines on how to
write programs that will compile correctly under all CL implementations.


Discussion:

Reaction to an earlier version of this proposal on the CL mailing list was
overwhelmingly positive.

The only major criticism of this proposal I have heard is that it should
also include PROCLAIM.  However, since PROCLAIM is not a macro, its
compile-time side effects cannot be handled using the same mechanism.
A separate proposal seems more appropriate.

-------

∂09-May-88  0855	CL-Compiler-mailer 	issue EVAL-WHEN-NON-TOP-LEVEL 
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 9 May 88  08:54:55 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA22855; Mon, 9 May 88 09:55:34 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805091555.AA22855@cs.utah.edu>
Date: Mon, 9 May 88 09:55:33 MDT
Subject: issue EVAL-WHEN-NON-TOP-LEVEL
To: cl-compiler@sail.stanford.edu


Issue:		EVAL-WHEN-NON-TOP-LEVEL
References:	CLtL p. 69-70
		Issue DEFINING-MACROS-NON-TOP-LEVEL
Category:	CLARIFICATION, ENHANCEMENT
Edit History:   6-May-88, V1 by Sandra Loosemore


Problem Description:

The current description of how the compiler should handle EVAL-WHEN
only makes sense when it appears as a top-level form in the file being
compiled.  Other proposals being considered by the compiler cleanup
committee require that we clarify how the compiler should process
EVAL-WHENs appearing at non-top-level, such as within LET or FUNCTION
special forms. 


Proposal:  EVAL-WHEN-NON-TOP-LEVEL:CLARIFY

There are three possible processing situations which may be specified
in EVAL-WHEN.  The interpreter pays attention to only the EVAL
situation, while the LOAD and COMPILE situations are handled by the
compiler. 

The EVAL situation corresponds to the normal processing of the
interpreter.  If EVAL is specified, the interpreter evaluates each
form in the body of the EVAL-WHEN as an implicit PROGN, using the
current lexical environment.  If the EVAL situation is not specified,
then the interpreter must return NIL as the value of the EVAL-WHEN
form, without evaluating the body. 

The LOAD situation corresponds to the normal processing of the
compiler.  To the compiler, (EVAL-WHEN (LOAD) ...) is equivalent to a
PROGN form; the compiler simply arranges for the body to be
``evaluated'' in the lexical environment in which the EVAL-WHEN form
appears.  If the LOAD situation is not specified, the compiler
arranges for the EVAL-WHEN form to return a value of NIL without
evaluating the body forms.  (The name LOAD is something of a misnomer,
because ``evaluation'' happens not at LOAD time, but when the
EVAL-WHEN form would normally be ``evaluated''.  For example, if an
EVAL-WHEN form appears in the body of a DEFUN, it is ``evaluated''
when that function is called.)

The EVAL and LOAD situations are therefore quite similar and
correspond to normal evaluation semantics.  That is, one could
consider that each form and nested subform is implicitly wrapped with
an (EVAL-WHEN (EVAL LOAD) ...). 

The COMPILE situation indicates that the compiler itself should
evaluate the body of the EVAL-WHEN form as an implicit PROGN in the
null lexical environment.  During the evaluation, if a nested
EVAL-WHEN appears in the body, the interpreter follows its usual rule
of checking only whether or not the EVAL situation is specified to
decide whether or not the body of the nested EVAL-WHEN should be
processed. 

If both the COMPILE and LOAD situations are specified, the compiler
first performs the evaluation for the COMPILE situation.  Then, the
normal processing for the LOAD situation takes place, except that the
compile-time evaluation of nested (EVAL-WHEN (COMPILE) ...) forms in
the body is suppressed, preventing repeated evaluations of subforms.

(EVAL-WHEN (COMPILE) ...) should be used with caution in non-top-level
situations.  For example, if the following appears as a top level form
in a file being compiled

    (let ((x  (some-hairy-computation)))
        (eval-when (eval compile load) (print x)))

the variable X will be treated as special during the compile-time
evaluation, and the value printed will be its symbol-value.  To
guarantee consistency between compile-time evaluation and the normal
processing, one should wrap the entire top-level form in an EVAL-WHEN,
as follows:

    (eval-when (eval-compile load)
        (let ((x  (some-hairy-computation)))
	    (print x)))


Rationale:

The behavior of top-level EVAL-WHENs as specified in this proposal
remains almost identical to that specified in CLtL.  The major
addition is specifying the lexical environment in which non-top-level
EVAL-WHENs are processed.  It is clear that the COMPILE situation must
always be processed in the null lexical environment, since the actual
lexical environment is not available at compile time.  Having the EVAL
and LOAD situations evaluate in the proper environment leads to
differing semantics, but it appears to be the behavior that most
people expect.

Suppression of COMPILE evaluations in nested EVAL-WHENs is necessary
to achieve certain desirable behaviors, such as the macro example in
section 4 of the DEFINING-MACROS-NON-TOP-LEVEL proposal.


Current Practice:


Cost to implementors:

Probably fairly minor in most implementations.  

As an implementation technique, we suggest implementing EVAL-WHEN as a 
macro which uses a state variable (rebound by EVAL, COMPILE, and
COMPILE-FILE) to keep track of the current context.

    (defmacro eval-when (situations &body body)
        (cond ((null *compiling-p*)
               (if (member 'eval situations)
                   `(progn ,@body)
                   'nil))
              ((and (member 'compile situations) (member 'load situations))
               (eval `(progn ,@body))
               `(macrolet ((eval-when (situations &body body)
                               (if (member 'load situations)
                                   `(progn ,@body)
                                   'nil)))
                    ,@body))
              ((member 'compile situations)
               (eval `(progn ,@body))
               'nil)
              ((member 'load situations)
               `(progn ,@body))
              (t 'nil)))


Cost to users:

Since CLtL does not currently specify what the meaning of EVAL-WHEN
forms at non-top-level is, existing code which depends on their use is
already nonportable.  Preventing repeated evaluations of subforms when
EVAL-WHENs are nested is unlikely to cause any serious compatibility
problems, since the current model would already result in only a
single evaluation in the case when the code is processed
interpretively.


Benefits:

Clarifying the meaning of EVAL-WHEN allows the behavior of defining
macros such as DEFMACRO to be specified in terms of EVAL-WHEN.  As a
side effect, it would then become meaningful for defining macros to
appear at other than top-level. 


Discussion:

This proposal reflects what appears to be the consensus of the
compiler cleanup committee on this issue.

-------

∂09-May-88  0856	CL-Compiler-mailer 	issue DEFINING-MACROS-NON-TOP-LEVEL
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 9 May 88  08:56:13 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA22960; Mon, 9 May 88 09:56:53 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805091556.AA22960@cs.utah.edu>
Date: Mon, 9 May 88 09:56:50 MDT
Subject: issue DEFINING-MACROS-NON-TOP-LEVEL
To: cl-compiler@sail.stanford.edu


Issue:		DEFINING-MACROS-NON-TOP-LEVEL
References:	CLtL p. 66-70, 143
		Issue EVAL-WHEN-NON-TOP-LEVEL
		Issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS
Category:	CLARIFICATION, ENHANCEMENT
Edit History:   6-May-88, V1 by Sandra Loosemore


Problem Description:

CLtL leaves the interpretation of defining forms such as DEFMACRO and
DEFVAR that appear in other than top-level locations unspecified.
Resolution of other issues (EVAL-WHEN-NON-TOP-LEVEL and
COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS) now allows reasonable
semantics to be assigned to defining forms which appear at
non-top-level.


Proposal: DEFINING-MACROS-NON-TOP-LEVEL:ALLOW

(1) Clarify that while defining macros normally appear at top level,
it is meaningful to place them in non-top-level contexts and that the
compiler must handle them properly in all situations.  Remove the
language on p. 66 of CLtL which states that the compiler is not
required to recognize defining macros at other than top-level.

(2) The proposal COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY
defines a model for specifying how defining macros work.  To
summarize, the expansion of the macro (rather than its expander
function) is responsible for storing information about the definition.
Compile-time side effects are typically handled by including one or
more EVAL-WHEN forms in the expansion.  Although a compiler may choose
some other implementation, such as treating defining macros as
implementation-specific special forms, the semantics must remain the
same.

(3) Defining macros which define functional objects (such as DEFUN and
DEFMACRO) must ensure that the functions are defined in the lexical
environment in which the defining macro appears.  In the model
referred to above, this would normally be implemented by producing a
FUNCTION special form in the macro expansion.  For example, the
following code causes the function BAR to be closed over the variable
X:

    (let ((x  (some-hairy-computation)))
        (defun bar (y) (+ x y)))

(4) The language on p. 145 of CLtL, which states that macro functions
are defined in the null lexical environment, should be removed.
Instead, defining forms such as DEFMACRO which make a functional
definition available at the compile time use the environment must
normally appear inside an explicit (EVAL-WHEN (COMPILE) ...) to ensure
that the correct lexical environment is seen. 

An example may help clarify why this is necessary.  The code fragment

    (let ((x  (some-hairy-computation)))
        (defmacro bar-macro (y) `(+ ,x ,y)))

would macroexpand into something similar to

    (let ((x  (some-hairy-computation)))
        (eval-when (eval compile load)
            (setf (macro-function 'bar-macro) 
	          #'(lambda (form env)
		        (let ((y  (second form)))
			    `(+ ,x ,y))))
            'bar-macro))

Since the rules for (EVAL-WHEN (COMPILE) ...) state that evaluation takes
place in the null lexical environment, in this situation X would be treated
as a special variable within the macro function.  However, in the EVAL or 
LOAD situations, the lexical value of X would be used.  To ensure 
consistency, the correct definition would be:

    (eval-when (eval compile load)
        (let ((x  (some-hairy-computation)))
            (defmacro bar (y) `(+ ,x ,y))))


Rationale:

The notion of a ``top-level form'' is rather confused.  There has been
a suggestion that the notion of a top-level form should be extended to
include forms in the body of a top-level LET, to allow forms such as
DEFUN to be meaningful there.  However, we feel that a cleaner
solution is to remove the restrictions on the placement of defining
macros altogether.


Current Practice:


Cost to implementors:


Cost to users:

None.  This is a compatible extension.


Benefits:

The notion of top-level forms as being somehow special is removed from
the language.  Allowing defining macros to appear anywhere instead of
restricting them to certain positions results in a cleaner language
design.


Discussion:

-------

∂10-May-88  2314	CL-Compiler-mailer 	subcommittee meeting(s)  
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 10 May 88  23:14:11 PDT
Received: by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA11863; Tue, 10 May 88 23:14:03 PDT
Received: by franz (5.5/3.14)
	id AA13520; Tue, 10 May 88 22:29:34 PDT
Received: by feast (5.5/3.14)
	id AA01569; Wed, 11 May 88 01:20:30 EDT
Date: Wed, 11 May 88 01:20:30 EDT
From: franz!feast!smh@ucbarpa.Berkeley.EDU (Steven M. Haflich)
Message-Id: <8805110520.AA01569@feast>
To: cl-compiler@sail.stanford.edu
Subject: subcommittee meeting(s)

  Time to schedule the compiler-cleanup subcommittee for June X3J13.
Last time in Palo Alto we actually made some progress.  Now we need to
continue towards real written proposals.  Be there or be interpreted!
  Scheduling is tricky, as ever, paarticular acommodating travel for
out-of-towners.  Several of us are involved with the Definition Specs
meeting 3:00-5:30 Tuesday.  We probably need a fair amount of time to
work through details -- a single 2-3 hour meeting probably wouldn't be
enough.  So either we schedule a single long meeting, or two shorter
ones.
  I would be very happy with a Tuesday evening meeting and a Thursday
evening or Friday morning meeting.  This might be convenient for
out-of-towners.  (I *think* I would be able to find a meeting place,
assuming Symbolics might not be available outside office hours.)  The
alternative would be to start early Tuesday, but this would require an
extra night for West Coast people.
  If you have particular travel and/or time restrictions, please
respond asap so I can work out the details.  If I *don't* hear, I'll
just make an arbitrary decision.

∂12-May-88  1826	CL-Compiler-mailer 	subcommittee meeting(s)  
Received: from labrea.stanford.edu by SAIL.Stanford.EDU with TCP; 12 May 88  18:25:54 PDT
Received: by labrea.stanford.edu; Thu, 12 May 88 18:12:48 PDT
Received: from bhopal.lucid.com by edsel id AA09585g; Thu, 12 May 88 18:17:42 PDT
Received: by bhopal id AA23990g; Thu, 12 May 88 18:20:46 PDT
Date: Thu, 12 May 88 18:20:46 PDT
From: Jon L White <edsel!jonl@labrea.stanford.edu>
Message-Id: <8805130120.AA23990@bhopal.lucid.com>
To: franz!feast!smh@ucbarpa.berkeley.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Steven M. Haflich's message of Wed, 11 May 88 01:20:30 EDT <8805110520.AA01569@feast>
Subject: subcommittee meeting(s)

Since traving West-to-East means a three-hour time shift in the "wrong"
direction, I strongly prefer late-afternoon and evening meetings to
any morning meetings.

-- JonL --

∂16-May-88  1244	CL-Compiler-mailer 	Re: COMPILE-FILE-OF-TOP-LEVEL-FORMS
Received: from hudson.dec.com by SAIL.Stanford.EDU with TCP; 16 May 88  12:44:39 PDT
Date: 16 May 88 15:32:00 EDT
From: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>
Subject: Re: COMPILE-FILE-OF-TOP-LEVEL-FORMS
To: "cl-compiler" <cl-compiler@sail.stanford.edu>
cc: vanroggen   
Reply-To: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>

It's good to some of these things written down.  Here are my comments
so far...

I think the issue name is a bit too general--how about
COMPILE-FILE-OF-DEFINING-MACROS, since it just talks about
DEFxxx forms, with the "top-level" assumed.

If we don't want to address inter-file dependencies in this issue,
we should say so explicitly.

Although this is an issue that comes with PROCLAIM, it's probably
worthwhile mentioning that when COMPILE-FILE sees a DEFUN, it may
decide to keep the body of the function around due to INLINE
proclamations.  VAX LISP requires INLINE proclamations to come
before the corresponding DEFUNs, because we don't want to keep around
all the source code ever seen just in case an INLINE proclamation/declaration
might come much later.

  "If the initial value form [of a DEFCONSTANT] is a constant, an
   implementation may also choose to evaluate it at compile time for
   the purposes of constant-folding."
Firstly, if the value is a constant, it may be evaluated at any time--
so this sentence doesn't say much.  [Or is the referent of "it" the
DEFCONSTANT expression?]  Secondly, I think it's more important to state
what an implementation -cannot- do, much as was stated for DEFVAR.
I think of DEFCONSTANT and DEFPARAMETER being very similar, except that
constants can't be set or bound.  I don't see why that would suddenly
allow the compiler to evaluate the inital value form at compile time.
So we should say that the initial value form must not be evaluated at
compile time.

For DEFSETF and DEFINE-SETF-METHOD, add the comment (as is included
for DEFMACRO) that the expansion needn't be evaluable at compile time.

Question: must the expansion of a DEFTYPE be a legitimate type at compile
time?

			---Walter
------

∂16-May-88  2307	CL-Compiler-mailer 	issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS    
Received: from labrea.stanford.edu by SAIL.Stanford.EDU with TCP; 16 May 88  23:07:21 PDT
Received: by labrea.stanford.edu; Mon, 16 May 88 23:07:44 PDT
Received: from bhopal.lucid.com by edsel id AA28744g; Mon, 16 May 88 22:57:04 PDT
Received: by bhopal id AA03382g; Mon, 16 May 88 23:00:22 PDT
Date: Mon, 16 May 88 23:00:22 PDT
From: Jon L White <edsel!jonl@labrea.stanford.edu>
Message-Id: <8805170600.AA03382@bhopal.lucid.com>
To: sandra@cs.utah.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Sandra J Loosemore's message of Mon, 9 May 88 09:54:35 MDT <8805091554.AA22789@cs.utah.edu>
Subject: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS

One thing bothers me muchly about this proposal -- it re-inforces the old
MacLisp notion of "specially noticing" certain forms at top level without
evaluating them; in particular the MacLisp Compiler had a separate database
which held macro definitions "noticed" in the file being compiled, but
which hadn't been explicitly evaluated.

What I particularly dislike is the half-supported status of "noticed" things;
why will a macro be expandable by the compiler but not by the interpreter?  
The many ways in which things can be "noticed", and the meaning of "notice",
is very opaque.

Instead, I'd prefer the issue to be simply "To Evaluate, or Not to
Evaluate, That Is the Question".  In short, every form should fall
into one of four categories:
  (1) Function definition, in which case not only is the body compiled
      but the compiler is permitted to "remember" certain aspects of
      the function, such as argument spectrum for subsequent user-friendly
      warning messages, and such as source-code for subsequent INLINEing.
      [Macro definitions can come under this clause too; but they could
      also be listed both in (1) and (2).]
  (2) Explicitly-listed form that is implicitly eval-when(eval compile load);
      "implicitly" means, "if the user didn't wrap an eval-when around it,
      then the compiler puts the 'implicit' one in;" however, any user
      supplied eval-when overrides this implicit behaviour.  There is already
      a precedent with several of the "Seven Extremely Randoms".
  (3) An EVAL-WHEN form; explicit semantics for such toplevel forms will be 
      forthcoming; anyway, it ought to be obvious.
  (4) Any other form not in (1) through (3); such is merely compiled and 
      "shoved" out into the compiler output file.
Because of the need to treat IN-PACKAGE and possibly other "7 randoms"
this way, I don't think we could every reduce (2) to the null set.  I admit
that putting too many functions in it would confuse things (making it
harder to remember just what was there).  But for starters, why not
all the DEF... forms you listed in your proposal, except for DEFUN and
DEFVAR (and DEFPARAMETER, which is a trivial variant of DEFVAR).  This 
would mean every CLtL DEF... form (except for the exceptions) is implicitly 
evaluated during compilation; when this is undesirable, the user would have 
the burden of explicitly wrapping eval-when (eval load) around the form.

I fear that my simplified proposal is what you initially offered a long
time ago, and were beaten back on.  But I offer my support for it now,
if clarifying is what you want to do.


-- JonL --

∂17-May-88  0739	CL-Compiler-mailer 	Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 17 May 88  07:39:32 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA24901; Tue, 17 May 88 08:39:05 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805171439.AA24901@cs.utah.edu>
Date: Tue, 17 May 88 08:39:04 MDT
Subject: Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS
To: edsel!jonl@labrea.stanford.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Jon L White <edsel!jonl@labrea.stanford.edu>, Mon, 16 May 88 23:00:22 PDT

  Date: Mon, 16 May 88 23:00:22 PDT
  From: Jon L White <edsel!jonl@labrea.stanford.edu>

  One thing bothers me muchly about this proposal -- it re-inforces the old
  MacLisp notion of "specially noticing" certain forms at top level without
  evaluating them; in particular the MacLisp Compiler had a separate database
  which held macro definitions "noticed" in the file being compiled, but
  which hadn't been explicitly evaluated.

That situation was exactly what this proposal (actually group of
proposals) was trying to get rid of, not re-inforce.  The compiler need
not do any "special noticing" of these defining macros at all, because
the model Steve and I have proposed is that the macros expand into
EVAL-WHENs to wrap the actions that should be performed at
compile-time.  All the compiler needs to recognize is EVAL-WHEN (and the
N ugly package functions). The actions, such as storing macro
definitions, may be (but are not required to be) handled identically in
both the interpreter and the compiler.

  What I particularly dislike is the half-supported status of "noticed" things;
  why will a macro be expandable by the compiler but not by the interpreter?  

I don't understand this.  The compiler must expand all the macros it runs
across, and so must the interpreter.

The big problem I have with your simplified counterproposal is that few
(if any) implementations already work that way, and I do not believe
that the behavior it specifies is what users really want or expect to
happen.

-Sandra
-------

∂17-May-88  2241	CL-Compiler-mailer 	issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS    
Received: from labrea.stanford.edu by SAIL.Stanford.EDU with TCP; 17 May 88  22:41:40 PDT
Received: by labrea.stanford.edu; Tue, 17 May 88 22:42:08 PDT
Received: from bhopal.lucid.com by edsel id AA03485g; Tue, 17 May 88 22:30:18 PDT
Received: by bhopal id AA07755g; Tue, 17 May 88 22:33:43 PDT
Date: Tue, 17 May 88 22:33:43 PDT
From: Jon L White <edsel!jonl@labrea.stanford.edu>
Message-Id: <8805180533.AA07755@bhopal.lucid.com>
To: sandra@cs.utah.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Sandra J Loosemore's message of Tue, 17 May 88 08:39:04 MDT <8805171439.AA24901@cs.utah.edu>
Subject: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS

re: That situation was exactly what this proposal (actually group of
    proposals) was trying to get rid of, not re-inforce.   ...
    the model Steve and I have proposed is that the macros expand into
    EVAL-WHENs to wrap the actions that should be performed at
    compile-time.  

Gleeep!  I've completly misread the intent of your proposal.  I believe
I misread it because the first n paragraphs of your PROPOSAL: section
reads like a problem description.  Two things need to be done (so I
think) to clarify this: (1) very early mention that this is what you
want to happen -- that compiler "noticing" is merely reduced to usages
of EVAL-WHEN; (2)  be much more specific as to what gets EVALuated at
compile time -- the listing of desirable effects in the "proposal" 
section is ok, but not specific enough to believe that they are all
being accomplished via normal EVAL-WHEN(...COMPILE...).

re:     What I particularly dislike is the half-supported status of "noticed" 
        things; why will a macro be expandable by the compiler but not by the 
        interpreter?  
    I don't understand this.  The compiler must expand all the macros it runs
    across, and so must the interpreter.

Well you yourself added the phrase:

    The actions, such as storing macro definitions, may be (but are not 
    required to be) handled identically in both the interpreter and the 
    compiler.

and it is this uncertainty about "not required to be" -- about the non-
equivalence of EVAL and EVAL-WHEN(...COMPILE...) -- that bothers me.


True, no implementation operates exactly like my simplified counter.  But 
they are not far from it.  Probably most are in accord with it on DEFUN,
DEFVAR, and DEFPARAMETER; and Lucid is in accord also on DEFCONSTANT,
DEFMACRO, and DEFTYPE.  Also Lucid is "mostly" in accord on DEFSTRUCT in 
that it does exactly the same thing as evaluating the defstruct, but doesn't 
actually install anything in the symbol-function cells (i.e., it makes
the TYPE entry, makes compiler macros for the functions etc.).

The hardest "pill" to swallow is to decide to make DEFSTRUCT, DEFMACRO, 
and DEFTYPE implicitly eval-when(eval compile load) Actually, the 
"simplified counter" doesn't depend on which of the varous forms are 
promoted to the "implicit" status and which aren't -- it merely tries to 
make a uniform interpretation when interpreting and compileing forms that 
affect the compilation process.


-- JonL --

∂18-May-88  1104	CL-Compiler-mailer 	issue EVAL-WHEN-NON-TOP-LEVEL 
Received: from labrea.stanford.edu by SAIL.Stanford.EDU with TCP; 18 May 88  11:04:00 PDT
Received: by labrea.stanford.edu; Wed, 18 May 88 02:14:56 PDT
Received: from bhopal.lucid.com by edsel id AA04028g; Wed, 18 May 88 01:59:26 PDT
Received: by bhopal id AA08279g; Wed, 18 May 88 02:02:52 PDT
Date: Wed, 18 May 88 02:02:52 PDT
From: Jon L White <edsel!jonl@labrea.stanford.edu>
Message-Id: <8805180902.AA08279@bhopal.lucid.com>
To: sandra@cs.utah.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Sandra J Loosemore's message of Mon, 9 May 88 09:55:33 MDT <8805091555.AA22855@cs.utah.edu>
Subject: issue EVAL-WHEN-NON-TOP-LEVEL

The early part of the Proposal: section probably ought to outline our
intent in giving ordinary macro semantics to EVAL-WHEN -- it is so that 
an piece of source code will either be "processed" as if the body of the 
eval-when is there, or as if it were not there, depending on the dynamic 
state of the processor:


    Original Source    |    Situation Applies   |  Situation Doesn't Apply
-----------------------+------------------------+----------------------------
                       |                        |
  (defun foo (x)       |     (defun foo (x)     |     (defun foo (x)     
    (step1 x)          |       (step1 x)        |       (step1 x)
    (eval-when (...)   |       (step2 x)        |       nil
      (step2 x))       |       (step2 x))       |       (step3 x))
    (step3 x))         |                        |

On can infer this from a careful reading of the proposal, but the 
overwhelming simplicity of making eval-when a small macro is lost "in the 
woods".  This top-level view of the proposal ought to be said very early 
in the proposal, rather than starting out with a myriad of details about 
how the various situations are treated.

I note also that you implicitly assume a dynamic variable *compiling-p*?
This will have to be spelled out in detail, much as in my note of
25 Mar 88 23:21:23 PST "Eval-When -- a radical view";  simply being
"in the compiler" isn't enough since EVAL may have to bind this variable
to nil (or do the equivalent -- Rob points out that we don't really
want to tie down the implementation to an actual dynamic variable, but
rather to the semantics give by the example code).

I very much like the idea of shadowing eval-when with a macrolet in the
situation where there might be nested eval-when's and the outter one has 
at least a 'compile' situation.  In fact, the trial code I sent out in
the msg "Eval-When -- a radical view" doesn't work right;  the attempt
to identify this circumstance with a dynamic binding of a state variable 
(to :eval-before-compile) is wrong, since it really is a lexical effect 
that is needed, not a dynamic one.

Finally, I had a bit of trouble following all the logic in all the 
cond clauses of the sample defmacro for EVAL-WHEN.   Could I offer a 
rewrite, with effusive commentary, that breaks it down into basically
two cases: the "hard" case (presented first) and the "easy" one.

    (defmacro eval-when (situations &body body)
      (cond ((and *compiling-p*
		  (member 'compile situations))
	      ;; Situation Applies: The hard case.  Compiling, and evaluation
	      ;;  is required at compile time too.
	     (eval `(progn ,@body))
	     (if (member 'load situations)
		  ;; Allow normal processing by 'compile-form-to-file',
		  ;;  except ignore sub requests for compile-time evaluation.
		  `(macrolet ((eval-when (situations &body body)
			       (if (member 'load situations)
				   `(PROGN ,@body)
				   'NIL)))
		    ,@body)
		  ;; or skip processing by 'compile-form-to-file'
		  `NIL))
	    ((if *compiling-p*
		 (member 'load situations)
		 (member 'eval situations))
	      ;; Situation Applies: The easy case.  Just return the body code 
	      ;;  for normal processing by 'eval' or 'compile-form-to-file'.
	     `(PROGN ,@body))
	    (t 
	      ;; Hmmm, 'situation' just doesn't apply!
	     `NIL)))



-- JonL --

∂18-May-88  1152	CL-Compiler-mailer 	proposals 
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 18 May 88  11:52:03 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA29255; Wed, 18 May 88 08:55:04 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805181455.AA29255@cs.utah.edu>
Date: Wed, 18 May 88 08:55:03 MDT
Subject: proposals
To: cl-compiler@sail.stanford.edu

Unless I hear any objections Real Soon Now, I'm going to write up revised
versions of the proposals I sent out before to incorporate the suggestions
I've received and clean up the wording.  I hope to be able to get them out
by the weekend.

-Sandra
-------

∂19-May-88  1012	CL-Compiler-mailer 	subcommittee meeting(s)  
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 19 May 88  10:12:27 PDT
Received: by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA01979; Thu, 19 May 88 10:11:41 PDT
Received: by franz (3.2/3.14)
	id AA05387; Thu, 19 May 88 10:03:41 PDT
Received: by feast (5.5/3.14)
	id AA00668; Thu, 19 May 88 12:54:04 EDT
Date: Thu, 19 May 88 12:54:04 EDT
From: franz!feast!smh@ucbarpa.Berkeley.EDU (Steven M. Haflich)
Message-Id: <8805191654.AA00668@feast>
To: franz!cs.utah.edu!sandra
Cc: franz!sail.stanford.edu!cl-compiler
In-Reply-To: Sandra J Loosemore's message of Wed, 18 May 88 09:03:42 MDT <8805181503.AA29510@cs.utah.edu>
Subject: subcommittee meeting(s)

   From: fridge!ucbarpa!cs.utah.edu!sandra (Sandra J Loosemore)

   On the assumption that we will be meeting on Tuesday evening and on
   Friday, I've arranged to arrive late Tuesday afternoon.  (I will actually
   be staying until Sunday morning with the idea of spending all day Saturday
   visiting the local bookstores....)

Hereby announced.  Meetings will be Tuesday evening and Friday
morning, unless someone makes a compelling counterproposal.  I'll
further suggest that those of us who can should start Tuesday over
dinner at one of the many fine but reasonably-priced eating
establishments in Cambridge.  It would be useful to know when people
become available so we can pick exact times, but there's no urgency.

It's been overheard from the Character Subcommittee that evening
meetings at Symbolics are impossible because of security.  Therefore
I've arrange with Greenblatt to use a conference room at Gigamos.
Gigamos easy to get to -- it is within long walking distance of
Symbolics, and just steps from the Central Square subway stop.  I'll
post directions etc. later.

P.S.: Right now someone is working on franz's mailer, and it sometimes
generates bogus return addresses.  No problem -- I'll still receive
anything cc'd to cl-compiler@sail.

∂20-May-88  0825	CL-Compiler-mailer 	issue EVAL-WHEN-NON-TOP-LEVEL 
Received: from hudson.dec.com by SAIL.Stanford.EDU with TCP; 20 May 88  08:25:46 PDT
Date: 20 May 88 11:19:00 EDT
From: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>
Subject: issue EVAL-WHEN-NON-TOP-LEVEL
To: "cl-compiler" <cl-compiler@sail.stanford.edu>
cc: vanroggen   
Reply-To: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>

Overall, this proposal looks pretty good, if a clarification and "compatible"
extension is what we want.

I think that in addition to specifying the environments for the different
situations, the major change in this proposal may appear to be the meaning of
the LOAD situation.  I would like to believe that the intent of the LOAD
situation has always been to make the body of the EVAL-WHEN be compiled, not
the more obvious intent (judging by the name) of EVALuating the body when the
compiled file is being LOADed.

The latter interpretation is perfectly consistent with the former as long as
the EVAL-WHEN is at top-level in the file. Since we want to assign a meaning to
EVAL-WHEN when not at top-level, the former interpretation makes more sense and
would be compatible between the old and the new semantics.

Another reason why this interpretation is necessary is that non-top-level
EVAL-WHEN's ought to work fine when COMPILE is being used to compile
functions, not just when used in files being processed by COMPILE-FILE.

I believe that explicitly stating this interpretation will make it easier
for people to understand why the LOAD situation doesn't mean what they may
think it means.  Although I believe my interpretation is what you mean to
say in
  To the compiler, (EVAL-WHEN (LOAD) ...) is equivalent to a
  PROGN form; the compiler simply arranges for the body to be
  ``evaluated'' in the lexical environment in which the EVAL-WHEN form
  appears.
it might still not be clear to some readers.  [But the macro definition
of EVAL-WHEN helps a lot.]  Perhaps a historical note about compilers
normally being file compilers will help also.

The related thing which people might be confused with is what happens
with "#,".  The reason why I suggested this proposal, which I agree with,
might not be sufficient is that it doesn't address the ability to
evaluate forms at LOAD time.  But maybe this proposal along with another
one to add a special form to do LOAD-time evaluation for side-effects
and constant-values will be acceptable.


A major nit (!?): Isn't there a cleanup proposal to disallow lexically
binding special-forms in FLET, LABELS, and MACROLET?  If so, your
EVAL-WHEN macro is doing a no-no.  You might want to change the statement
from "suggested implementation technique" to "implemented as if".

For the Current Practice section, VAX LISP implements the proposed
changes already, except that it doesn't always substitute NIL when the
situation doesn't apply.  (There are times when the whole form just
disappears rather than returning NIL.)

			---Walter
------

∂20-May-88  1158	CL-Compiler-mailer 	Re: issue EVAL-WHEN-NON-TOP-LEVEL  
Received: from FRED.SLISP.CS.CMU.EDU by SAIL.Stanford.EDU with TCP; 20 May 88  11:58:12 PDT
Received: from FRED.SLISP.CS.CMU.EDU by FRED.SLISP.CS.CMU.EDU; 20 May 88 14:59:54 EDT
To: sandra@cs.utah.edu (Sandra J Loosemore)
cc: cl-compiler@sail.stanford.edu
Subject: Re: issue EVAL-WHEN-NON-TOP-LEVEL 
In-reply-to: Your message of Mon, 09 May 88 09:55:33 -0600.
             <8805091555.AA22855@cs.utah.edu> 
Date: Fri, 20 May 88 14:59:13 EDT
From: Rob.MacLachlan@WB1.CS.CMU.EDU


This is a reasonable approach to making EVAL-WHEN well defined, but there
seems to be a problem when the COMPILE situation is specified without the
EVAL situation.  In this form, I believe (FOO) would never be evaluated in
any context, which is definitely an incompatible change:
    (eval-when (compile)
      (eval-when (compile)
	(foo)))

Admittedly, I have argued in the past that it is never meaningful to
specify the COMPILE situation without the EVAL situation, but if the intent
is to fix up EVAL-WHEN, then we should attempt to be as compatible as
possible.

But perhaps this is worked around by the usage of *in-the-compiler*?  It
definitely needs to be made clearer what exactly is being done with that
varaible where.  But if my above interpretation of nested uses of the
COMPILE situation is incorrect, then the text description should also be
changed, since it seems to be consistent with my interpretation.

As far as explanation of what EVAL-WHEN does, I think there should be
explicit mention of the fact that only the outermost use of the COMPILE
situation nulls the evaluation environment.  This implied by the sample
implementation, and is exploited by your DEFMACRO environment example, but
should be made more explicit.

I agree with Jonl's remarks about the presentation of the proposal.

  Rob

∂20-May-88  1208	CL-Compiler-mailer 	Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS     
Received: from FRED.SLISP.CS.CMU.EDU by SAIL.Stanford.EDU with TCP; 20 May 88  12:08:19 PDT
Received: from FRED.SLISP.CS.CMU.EDU by FRED.SLISP.CS.CMU.EDU; 20 May 88 15:09:55 EDT
To: sandra@cs.utah.edu (Sandra J Loosemore)
cc: cl-compiler@sail.stanford.edu
Subject: Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS 
In-reply-to: Your message of Mon, 09 May 88 09:54:35 -0600.
             <8805091554.AA22789@cs.utah.edu> 
Date: Fri, 20 May 88 15:09:45 EDT
From: Rob.MacLachlan@WB1.CS.CMU.EDU


This is a fair summary of current practice, but I would rather push through
a proposal that is more aggressive in defining the exact effects of
compiler processing.

Like Jonl, I favor saying that forms like DEFMACRO are actually truly,
honest to God evaluated by the compiler.  This could be done by an
expansion that includes an EVAL-WHEN, but it should be required that all
Common Lisp semantics of evaluation of that defining form should be present
in the compiler environment after the implicit evaluation.

It could be a bit icky actually installing the DEFSTRUCT slot accessors,
but this could be finessed by pretending that the slot accessors expand to
DEFUNs outside of the EVAL-WHEN.

I strongly, totally, completely disagree with VanRoggen's remarks about
DEFCONSTANT.  From my perspective, the reason for DEFCONSTANT is permissive
rather restrictive.  You define constants so that the compiler can use
information about that name at compile time.  I believe that DEFCONSTANT
should also be implicitly evaluated at compile time.  This means that the
value form *must always* be evaluable at compile time.  This is a slight
departure from current practice, but a sensible and useful one.

  Rob

∂20-May-88  1229	CL-Compiler-mailer 	Re: issue EVAL-WHEN-NON-TOP-LEVEL  
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 20 May 88  12:29:53 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA05454; Fri, 20 May 88 13:29:59 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805201929.AA05454@cs.utah.edu>
Date: Fri, 20 May 88 13:29:58 MDT
Subject: Re: issue EVAL-WHEN-NON-TOP-LEVEL 
To: Rob.MacLachlan@wb1.cs.cmu.edu
Cc: sandra@cs.utah.edu (Sandra J Loosemore), cl-compiler@sail.stanford.edu
In-Reply-To: Rob.MacLachlan@WB1.CS.CMU.EDU, Fri, 20 May 88 14:59:13 EDT

> Date: Fri, 20 May 88 14:59:13 EDT
> From: Rob.MacLachlan@WB1.CS.CMU.EDU
> 
> This is a reasonable approach to making EVAL-WHEN well defined, but there
> seems to be a problem when the COMPILE situation is specified without the
> EVAL situation.  In this form, I believe (FOO) would never be evaluated in
> any context, which is definitely an incompatible change:
>     (eval-when (compile)
>       (eval-when (compile)
> 	  (foo)))

Yes, you are correct that under the current proposal, (foo) would never
be evaluated.  I do not think it is "definitely" an incompatible change,
however.  The current wording in CLtL seems to leave this behavior
unspecified and I don't know what the original intention was.

-Sandra
-------

∂20-May-88  1303	CL-Compiler-mailer 	Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS     
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 20 May 88  13:03:39 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA06503; Fri, 20 May 88 14:03:57 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805202003.AA06503@cs.utah.edu>
Date: Fri, 20 May 88 14:03:55 MDT
Subject: Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS 
To: Rob.MacLachlan@wb1.cs.cmu.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Rob.MacLachlan@WB1.CS.CMU.EDU, Fri, 20 May 88 15:09:45 EDT

> Date: Fri, 20 May 88 15:09:45 EDT
> From: Rob.MacLachlan@WB1.CS.CMU.EDU
> 
> Like Jonl, I favor saying that forms like DEFMACRO are actually truly,
> honest to God evaluated by the compiler.  This could be done by an
> expansion that includes an EVAL-WHEN, but it should be required that all
> Common Lisp semantics of evaluation of that defining form should be present
> in the compiler environment after the implicit evaluation.
> 
> It could be a bit icky actually installing the DEFSTRUCT slot accessors,
> but this could be finessed by pretending that the slot accessors expand to
> DEFUNs outside of the EVAL-WHEN.

These two paragraphs seem mutually contradictory.  If you want to make
all of the defining macros implicitly EVAL-WHEN (EVAL COMPILE LOAD), like
the N random package functions, then you're going to get the defstruct
slot accessor functions defined at compile time, too.  If you want the
defining macros to make some things available at compile time and other
things not, I think you either have to use EVAL-WHEN in the expansion
or have the compiler treat every one of these guys like a special form.

Again, the proposal as written appears to be fairly close to current
practice.  Other than KCL, I don't know of any implementation that fully
evaluates DEFUN forms at compile time, and I don't know of any
implementation that doesn't do something special with DEFMACRO and
DEFVAR.  In some implementations, the compile-time side-effects of
DEFMACRO make the macro defined in exactly the same way as if the form
had been evaluated by the interpreter, and in others the macro
definition is stored someplace where the compiler can see it but the
interpreter can't.  Some people have made a fairly strong argument that
compilation side-effects should not affect the interpreter at all.

I think it would be nice to be able to definitely specify one way or the
other, either that the side-effects must be identical in the compiler to
what they are in the interpreter, or that the side effects must not be
visible to the interpreter at all.  However, I think the diversity of
opinion on this issue might prevent us from getting the rest of the
proposal through to the full committee, and I think it is *very*
important that we do that as soon as we can.  That is why the current
proposal explicitly leaves this behavior unspecified.  If we eventually
reach agreement to tighten it up one way or the other later on, there is
nothing to prevent us from presenting another proposal to amend this
one.  I just don't see that happening in the next few weeks.

-Sandra
-------

∂20-May-88  1354	CL-Compiler-mailer 	Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS     
Received: from FRED.SLISP.CS.CMU.EDU by SAIL.Stanford.EDU with TCP; 20 May 88  13:54:26 PDT
Received: from FRED.SLISP.CS.CMU.EDU by FRED.SLISP.CS.CMU.EDU; 20 May 88 16:55:23 EDT
To: sandra@cs.utah.edu (Sandra J Loosemore)
cc: cl-compiler@sail.stanford.edu
Subject: Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS 
In-reply-to: Your message of Fri, 20 May 88 14:03:55 -0600.
             <8805202003.AA06503@cs.utah.edu> 
Date: Fri, 20 May 88 16:55:14 EDT
From: Rob.MacLachlan@WB1.CS.CMU.EDU


    From: sandra@cs.utah.edu (Sandra J Loosemore)
    Date: Fri, 20 May 88 14:03:55 MDT
    Subject: Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS 
    To: Rob.MacLachlan@wb1.cs.cmu.edu
    > Date: Fri, 20 May 88 15:09:45 EDT
    > From: Rob.MacLachlan@WB1.CS.CMU.EDU
    > 
    > Like Jonl, I favor saying that forms like DEFMACRO are actually truly,
    > honest to God evaluated by the compiler.
    [...] These two paragraphs seem mutually contradictory.

Well, not in my intent.  I don't include DEFUN in "forms like DEFMACRO".
The "forms like DEFMACRO" are:
    defmacro
    deftype
    defstruct
    define-setf-method
    defsetf
    defconstant

As a codification of current practice, the proposal is fine, but it doesn't
go nearly as far in specification as a good language design should.
Vagueness in specification is a powerful tool, but you shouldn't be vague
for no good reason.  The main reason that current practice is so diverse is
that this stuff was never standardized on, and for most programs *it
doesn't matter* as long as it falls within the general range you outline.
The problem with not being definite is that it encourages non-portability,
since the few programs that do care will work differently on different
implementations.

Having said that, I point out that I have no objection to this proposal
other than that it doesn't require the DEFCONSTANT value form to be
compile-time evaluable.  In all other ways it is compatible with my
compiler cleanup proposal, since its definition is so inclusive.

  Rob

∂20-May-88  1533	CL-Compiler-mailer 	Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS     
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 20 May 88  15:33:20 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA12692; Fri, 20 May 88 16:33:49 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805202233.AA12692@cs.utah.edu>
Date: Fri, 20 May 88 16:33:47 MDT
Subject: Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS 
To: Rob.MacLachlan@wb1.cs.cmu.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Rob.MacLachlan@WB1.CS.CMU.EDU, Fri, 20 May 88 16:55:14 EDT

I guess I'm not sure exactly what I should be more specific about in
this proposal, and how specific you all would like it to be.  I don't
think it would be appropriate to give code examples and say things like
"DEFMACRO *must* expand into *exactly* this set of forms".  The hooks
used by DEFSETF, for example, are necessarily quite implementation-specific
and it would be pointless to try to dictate what they must be.

What I've been trying to do is lay out what users must do to ensure that
their code is portable, and what implementions must and must not do.
Walter has already pointed out some particular things he'd like
mentioned, and if anybody else has something specific to add, I'd be
happy to hear about it.  I know I've left some things out just because
I didn't happen to think of them at the time I wrote this proposal!

-Sandra
-------

∂20-May-88  1627	CL-Compiler-mailer 	Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS     
Received: from FRED.SLISP.CS.CMU.EDU by SAIL.Stanford.EDU with TCP; 20 May 88  16:27:14 PDT
Received: from FRED.SLISP.CS.CMU.EDU by FRED.SLISP.CS.CMU.EDU; 20 May 88 18:55:14 EDT
To: sandra@cs.utah.edu (Sandra J Loosemore)
cc: cl-compiler@sail.stanford.edu
Subject: Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS 
In-reply-to: Your message of Fri, 20 May 88 16:33:47 -0600.
             <8805202233.AA12692@cs.utah.edu> 
Date: Fri, 20 May 88 18:55:09 EDT
From: Rob.MacLachlan@WB1.CS.CMU.EDU


    From: sandra@cs.utah.edu (Sandra J Loosemore)
    Date: Fri, 20 May 88 16:33:47 MDT
    Subject: Re: issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS 
    To: Rob.MacLachlan@wb1.cs.cmu.edu
    
    I guess I'm not sure exactly what I should be more specific about in
    this proposal, and how specific you all would like it to be.

This is the "compiler environment" issue.  Your proposal allows
implementations to attempt to maintain a separate compiler namespace.  This
capability is unnecessary for non-system code, and in the absence of
first-class environments, is too complex and/or vague to reasonably
specify.

Saying that the compile-time effect of processing a defining form is
required to be equivalent to that of evaluating it is more specific, and
not compatible with the concept of a compiler pseudo-environment.  In my
proposal I do allow that the compiler environment be disjoint from the
environment that compile-file is called in, but the compiler environment
must be a "real" environment.

The fact that systems need some way to protect the running Lisp from
compilation of system definitions is not an argument against flushing the
compiler environment as a Common Lisp concept.  Any Lisp system will
provide extensions that aid in bootstrapping the system; kludgey compiler
environment facilities can be enabled by a switch.

Once again, it isn't crucial that this issue be resolved now, since all
reasonable solutions are allowed by your proposal.  The only thing I
strongly object to is the treatment of the DEFCONSTANT value form.

  Rob

∂20-May-88  1647	CL-Compiler-mailer 	Re: issue EVAL-WHEN-NON-TOP-LEVEL  
Received: from FRED.SLISP.CS.CMU.EDU by SAIL.Stanford.EDU with TCP; 20 May 88  16:47:26 PDT
Received: from FRED.SLISP.CS.CMU.EDU by FRED.SLISP.CS.CMU.EDU; 20 May 88 17:04:53 EDT
To: sandra@cs.utah.edu (Sandra J Loosemore)
cc: cl-compiler@sail.stanford.edu
Subject: Re: issue EVAL-WHEN-NON-TOP-LEVEL 
In-reply-to: Your message of Fri, 20 May 88 13:29:58 -0600.
             <8805201929.AA05454@cs.utah.edu> 
Date: Fri, 20 May 88 17:04:48 EDT
From: Rob.MacLachlan@WB1.CS.CMU.EDU

   From: sandra@cs.utah.edu (Sandra J Loosemore)
    Message-Id: <8805201929.AA05454@cs.utah.edu>
    Date: Fri, 20 May 88 13:29:58 MDT
    Subject: Re: issue EVAL-WHEN-NON-TOP-LEVEL 
    To: Rob.MacLachlan@wb1.cs.cmu.edu
    
    > Date: Fri, 20 May 88 14:59:13 EDT
    > From: Rob.MacLachlan@WB1.CS.CMU.EDU
    > 
    >  In this form, I believe (FOO) would never be evaluated in
    > any context, which is definitely an incompatible change:
    >     (eval-when (compile)
    >       (eval-when (compile)
    > 	      (foo)))
    
    Yes, you are correct that under the current proposal, (foo) would never
    be evaluated.  I do not think it is "definitely" an incompatible change,
    however.  The current wording in CLtL seems to leave this behavior
    unspecified and I don't know what the original intention was.
    
I guess CLTL does leave that one hanging.  But this deserves at least some
compatibility/current practice note in the proposal.  This is incompatible
with at least our implementation.

The behavior you suggest seems non-intuitive to me.  The whole theory
behind EVAL-WHEN is that there are these independently composable
situations, any combination of which may be specified.  Specifying a
particular situation has a particular effect, independently of what other
situations are present.  In particular, specifying the COMPILE situation
guarantees that the body will be evaluated at compile time.

Of course, as I have pointed out before, the theory behind EVAL-WHEN is
wrong, so it isn't clear how upset we should be about mental models of
EVAL-WHEN being violated.

  Rob

∂21-May-88  0456	CL-Compiler-mailer 	issue EVAL-WHEN-NON-TOP-LEVEL 
Received: from labrea.stanford.edu by SAIL.Stanford.EDU with TCP; 21 May 88  04:56:45 PDT
Received: by labrea.stanford.edu; Sat, 21 May 88 04:57:03 PDT
Received: from bhopal.lucid.com by edsel id AA19600g; Sat, 21 May 88 04:39:11 PDT
Received: by bhopal id AA08170g; Sat, 21 May 88 04:42:51 PDT
Date: Sat, 21 May 88 04:42:51 PDT
From: Jon L White <edsel!jonl@labrea.stanford.edu>
Message-Id: <8805211142.AA08170@bhopal.lucid.com>
To: labrea!vanroggen%aitg.decnet@hudson.dec.com
Cc: cl-compiler@sail.stanford.edu, vanroggen@sail.stanford.edu
In-Reply-To: "AITG::VANROGGEN"'s message of 20 May 88 11:19:00 EDT <8805201736.AA15806@edsel.lucid.com>
Subject: issue EVAL-WHEN-NON-TOP-LEVEL

re: A major nit (!?): Isn't there a cleanup proposal to disallow lexically
    binding special-forms in FLET, LABELS, and MACROLET?  If so, your
    EVAL-WHEN macro is doing a no-no.  You might want to change the statement
    from "suggested implementation technique" to "implemented as if".

This proposal changes EVAL-WHEN from being a special-form into being a 
MACRO [that expands into some readily-understandable(?) code].  Thus it 
wouldn't be subject to the no-shadowing-of-special-forms rule.


-- JonL --

∂21-May-88  1200	CL-Compiler-mailer 	Re: issue EVAL-WHEN-NON-TOP-LEVEL  
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 21 May 88  12:00:24 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA28310; Sat, 21 May 88 10:11:26 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805211611.AA28310@cs.utah.edu>
Date: Sat, 21 May 88 10:11:25 MDT
Subject: Re: issue EVAL-WHEN-NON-TOP-LEVEL
To: Jon L White <edsel!jonl@labrea.stanford.edu>
Cc: labrea!vanroggen%aitg.decnet@hudson.dec.com, cl-compiler@sail.stanford.edu,
        vanroggen@sail.stanford.edu
In-Reply-To: Jon L White <edsel!jonl@labrea.stanford.edu>, Sat, 21 May 88 04:42:51 PDT

> Date: Sat, 21 May 88 04:42:51 PDT
> From: Jon L White <edsel!jonl@labrea.stanford.edu>
> 
> This proposal changes EVAL-WHEN from being a special-form into being a 
> MACRO [that expands into some readily-understandable(?) code].  Thus it 
> wouldn't be subject to the no-shadowing-of-special-forms rule.

Well, it doesn't go quite that far.  In the new, revised version of the
proposal, I was going to say that EVAL-WHEN behaves *as if* it were
implemented as a macro.  Changing its "official" status from special form
to macro is a somewhat larger step.  

I can think of cases where user code would still want to think of it as
a special form, particularly if we don't decide to make the *compiling-p*
variable public.  For instance, if you're trying to implement some kind
of a code-walking preprocessor, you would probably want it to leave the
EVAL-WHENs in place since the context in which the preprocessor executes
may not be the same as the context in which the code it produces is to
be processed.

I will bow to the wishes of the subcommittee on this issue.  I do think
we need to make a decision one way or the other and include the rationale
in the proposal, because somebody else is bound to bring it up later on.

-Sandra
-------

∂23-May-88  1124	CL-Compiler-mailer 	issue DEFINING-MACROS-NON-TOP-LEVEL
Received: from hudson.dec.com by SAIL.Stanford.EDU with TCP; 23 May 88  11:24:38 PDT
Date: 23 May 88 14:06:00 EDT
From: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>
Subject: issue DEFINING-MACROS-NON-TOP-LEVEL
To: "cl-compiler" <cl-compiler@sail.stanford.edu>
cc: vanroggen   
Reply-To: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>

This one looks pretty good too.

  Remove the
  language on p. 66 of CLtL which states that the compiler is not
  required to recognize defining macros at other than top-level.
Except this is still true:
    (let ((x (f)))
      (defmacro m (y) `(+ ,x ,y)))
    ...
    (defun g (...)
      ... (m ...) ...)
and inside G the use of M is an error because it isn't guaranteed to be
recognized as a call to a macro.  As you indicate later, using EVAL-WHEN
would provide a means of avoiding this problem.

Another example of this restriction:
    (defun f (...)
      ...
      (defstruct ship length ...)
      ... (ship-length ...) ...
      ...)
The use of SHIP-LENGTH in F is an error.

It would be worthwhile to remind readers that the names/bindings are
still global.  Thus in the defstruct example above,
there is not guaranteed to be a SHIP type until after F is called, there
might not be any SHIP-xxx functions until after F is called, and
all the names created by the DEFSTRUCT will be global.

			---Walter
------

∂24-May-88  1236	CL-Compiler-mailer 	new versions of proposals
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 24 May 88  12:35:59 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA04797; Tue, 24 May 88 13:36:10 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805241936.AA04797@cs.utah.edu>
Date: Tue, 24 May 88 13:36:09 MDT
Subject: new versions of proposals
To: cl-compiler@sail.stanford.edu

Coming up shortly (at long last) will be the revised versions of the
eval-when and defining macro proposals.  I apologize for taking so long;
the machine I was editing them on died a horrible death Friday afternoon
and is still in pieces, sigh.  Anyway, I have tried to clean up the
language and resolve some ambiguities that had previously gone
unnoticed.

So far I have received comments only from Walter about the third
proposal (about allowing defining macros in other than top-level
locations).  Does this mean everybody else is perfectly happy with it as
it stands?

-Sandra
-------

∂24-May-88  1236	CL-Compiler-mailer 	new, improved EVAL-WHEN proposal   
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 24 May 88  12:36:28 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA04812; Tue, 24 May 88 13:36:39 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805241936.AA04812@cs.utah.edu>
Date: Tue, 24 May 88 13:36:37 MDT
Subject: new, improved EVAL-WHEN proposal
To: cl-compiler@sail.stanford.edu

Issue:		EVAL-WHEN-NON-TOP-LEVEL
References:	CLtL p. 69-70
		Issue DEFINING-MACROS-NON-TOP-LEVEL
Category:	CLARIFICATION, ENHANCEMENT
Edit History:   6-May-88, V1 by Sandra Loosemore


Problem Description:

The current description of how the compiler should handle EVAL-WHEN
only makes sense when it appears as a top-level form in the file being
compiled.  Other proposals being considered by the compiler cleanup
committee require that we clarify how the compiler should process
EVAL-WHENs appearing at non-top-level, such as within LET or FUNCTION
special forms. 


Proposal:  EVAL-WHEN-NON-TOP-LEVEL:CLARIFY

In this proposal, we view EVAL-WHEN as a macro which expands into a
PROGN containing the body of the EVAL-WHEN when the context in which it
is expanded matches one of the situations listed, or NIL otherwise.
However, it is explicitly *not* proposed that EVAL-WHEN's status as
a special form be changed.

The EVAL situation corresponds to the normal processing of the
interpreter.  If EVAL is specified, the interpreter evaluates each
form in the body of the EVAL-WHEN as an implicit PROGN, using the
current lexical environment.  If the EVAL situation is not specified,
then the interpreter must return NIL as the value of the EVAL-WHEN
form, without evaluating the body. 

The LOAD situation corresponds to the normal processing of the
compiler.  If LOAD is specified, the compiler treats the EVAL-WHEN as
a PROGN and compiles the body in the normal way in the appropriate
lexical environment.  Otherwise, the form is equivalent to specifying
a constant value of NIL.  (The name LOAD is something of a misnomer,
because ``evaluation'' of the body happens not at LOAD time, but when
the EVAL-WHEN form would normally be ``evaluated''.  For example, if
an EVAL-WHEN form appears in the body of a DEFUN, it is ``evaluated''
when that function is called.)

The COMPILE situation is a special case; it indicates that the
compiler itself should evaluate the body of the EVAL-WHEN form as an
implicit PROGN in the null lexical environment.  During the
evaluation, if a nested EVAL-WHEN appears in the body, the interpreter
follows its usual rule of checking only whether or not the EVAL
situation is specified to decide whether or not the body of the nested
EVAL-WHEN should be processed. 

If both the COMPILE and LOAD situations are specified, the compiler
first performs the evaluation for the COMPILE situation.  Then, the
normal processing for the LOAD situation takes place, except that the
compile-time evaluation of nested (EVAL-WHEN (COMPILE) ...) forms in
the body is suppressed, preventing repeated evaluations of subforms.

(EVAL-WHEN (COMPILE) ...) should be used with caution in non-top-level
situations.  For example, if the following appears as a top level form
in a file being compiled

    (let ((x  (some-hairy-computation)))
        (eval-when (eval compile load) (print x)))

the variable X will be treated as special during the compile-time
evaluation, and the value printed will be its symbol-value.  To
guarantee consistency between compile-time evaluation and the normal
processing, one should wrap the entire top-level form in an EVAL-WHEN,
as follows:

    (eval-when (eval-compile load)
        (let ((x  (some-hairy-computation)))
	    (print x)))


Rationale:

The behavior of top-level EVAL-WHENs as specified in this proposal
remains almost identical to that specified in CLtL.  The major
addition is specifying the lexical environment in which non-top-level
EVAL-WHENs are processed.  It is clear that the COMPILE situation must
always be processed in the null lexical environment, since the actual
lexical environment is not available at compile time.  Having the EVAL
and LOAD situations evaluate in the proper environment leads to
differing semantics, but it appears to be the behavior that most
people expect, and it is also the easiest to implement.

Suppression of COMPILE evaluations in nested EVAL-WHENs is necessary
to achieve certain desirable behaviors, such as the macro example in
section 4 of the DEFINING-MACROS-NON-TOP-LEVEL proposal.

Although viewing EVAL-WHEN as a macro is useful for purposes of 
explanation, user code is likely to want to continue to treat EVAL-WHEN
as a special form.  For example, a preprocessor that performs a code
walk should leave EVAL-WHENs intact, since the context in which the
preprocessor runs may not be the same as the context in which the code
it produces runs.


Current Practice:


Cost to implementors:

Probably fairly minor in most implementations.  

As an implementation technique, we suggest implementing EVAL-WHEN as a 
macro which uses a state variable to keep track of the current context.
A sample implementation might look something like:

    (defvar *compiling-p* nil "Are we compiling or interpreting?")
    
    (defmacro eval-when (situations &body body)
        (cond 
    
              ;; If the COMPILE situation applies, evaluate the body now
              ;;    and also see if we need to do the LOAD situation too.
              ;;    If so, shadow the definition of EVAL-WHEN to make it
              ;;    ignore nested compile-time evaluation requests, and
              ;;    return the body.
    
              ((and *compiling-p* (member 'compile situations))
               (eval `(progn ,@body))
               (if (member 'load situations)
                   `(macrolet ((eval-when (situations &body body)
                                 (if (member 'load situations)
                                     `(progn ,@body)
                                     'nil)))
                        ,@body)
                   'nil))
    
              ;; If either the EVAL or LOAD situation applies, return a PROGN.
    
              ((if *compiling-p*
                   (member 'load situations)
                   (member 'eval situations))
               `(progn ,@body))
    
              ;; Otherwise no situation applies, so just return NIL.
    
              (t
               'nil)))
    
    
    ;;; Eval must bind *compiling-p* to NIL.
              
    (defun eval (form)
        (let ((*compiling-p* nil))
            :
            ))
    
    
    ;;; Compile and Compile-file must bind *compiling-p* to a non-nil value.
    
    (defun compile (name &optional definition)
        (let ((*compiling-p* t))
            :
            ))
    
    (defun compile-file (input-pathname &key output-file)
        (let ((*compiling-p* t))
            :
            ))


Cost to users:

Since CLtL does not currently specify what the meaning of EVAL-WHEN
forms at non-top-level is, existing code which depends on their use is
already nonportable.  Preventing repeated evaluations of subforms when
EVAL-WHENs are nested is unlikely to cause any serious compatibility
problems, since the current model would already result in only a
single evaluation in the case when the code is processed
interpretively.

There are also some situations concerning nested top-level occurences
of EVAL-WHEN that CLtL does not completely specify, to which this
proposal does assign a specific interpretation.  For example, CLtL is
unclear on whether or not (FOO) would ever be called, while in the
current proposal it would definitely not be called:

    (eval-when (compile)
        (eval-when (compile)
	    (foo)))


Benefits:

Clarifying the meaning of EVAL-WHEN allows the behavior of defining
macros such as DEFMACRO to be specified in terms of EVAL-WHEN.  As a
side effect, it would then become meaningful for defining macros to
appear at other than top-level. 


Discussion:

This proposal reflects what appears to be the consensus of the
compiler cleanup committee on this issue.

-------

∂24-May-88  1237	CL-Compiler-mailer 	new, improved defining macros proposal  
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 24 May 88  12:36:55 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA04849; Tue, 24 May 88 13:37:06 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805241937.AA04849@cs.utah.edu>
Date: Tue, 24 May 88 13:37:06 MDT
Subject: new, improved defining macros proposal
To: cl-compiler@sail.stanford.edu

Issue:		COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS
References:	CLtL pages 66-70, 143
Category:	CLARIFICATION
Edit history:   V1, 07 Oct 1987 Sandra Loosemore
                V2, 15 Oct 1987 Sandra Loosemore
                V3, 15 Jan 1988 Sandra Loosemore
		V4, 06 May 1988 Sandra Loosemore
		V5, 20 May 1988 Sandra Loosemore



Problem Description:

Standard programming practices assume that, when calls to defining
macros such as DEFMACRO and DEFVAR are processed by COMPILE-FILE,
certain side-effects occur that affect how subsequent forms in the
file are compiled.  However, these side-effects are not mentioned in
CLtL, except for a passing mention that macro definitions must be
``seen'' by the compiler before it can compile calls to those macros
correctly.  In order to write portable programs, users must know
exactly which defining macros have compile-time side-effects and what
those side-effects are. 

Inter-file compilation dependencies are distinct from, and not
addressed by, this issue. 


Proposal: COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY

(1) Clarify that defining macros such as DEFMACRO or DEFVAR, appearing
within a file being processed by COMPILE-FILE, normally have
compile-time side effects which affect how subsequent forms in the
same file are compiled.  A convenient model for explaining how these
side effects happen is that the defining macro expands into one or
more EVAL-WHEN forms, and that the calls which cause the compile-time
side effects to happen appear in the body of an (EVAL-WHEN (COMPILE)
...) form.  This is also the recommended implementation technique. 

(2) The affected defining macros and their specific side effects are
as follows:
 
DEFTYPE: The body of a DEFTYPE form must be evaluable at compile time.
If the expansion of a DEFTYPE'd type specifier is also a valid type
specifier at compile time, then the DEFTYPE'd type specifier is also
considered to be fully defined at compile time and must be recognized
within subsequent type declarations. 

DEFMACRO, DEFINE-MODIFY-MACRO:  Macro definitions must be stored at compile
time, so that occurences of the macro later on in the file will be expanded
correctly.  The body of the macro (but not necesarily its expansion) must 
be evaluable at compile time.
 
DEFUN: An implementation may choose to store information about the
function for the purposes of compile-time error-checking (such as
checking the number of arguments on calls), or to enable the function
to be expanded inline.  Portable code should not rely on DEFUN making
the function definition available at compile time.
 
DEFVAR, DEFPARAMETER: The compiler must recognize that the variables
named by these forms have been proclaimed special.  The initial value
form must not be evaluated at compile time. 
 
DEFCONSTANT: An implementation may choose to store information about
the variable for the purposes of compile-time error-checking, such as
checking for rebinding of or assignment to the variable.  The initial
value form must not be evaluated at compile time.  (If the initial
value is a constant, however, an implementation is allowed to
substitute the constant value for references to the named constant
during subsequent compilation.)
 
DEFSETF, DEFINE-SETF-METHOD: SETF methods must be available during the
expansion of calls to SETF later on in the file.  The body of
DEFINE-SETF-METHOD and the complex form of DEFSETF must be evaluable
at compile time, although the expansions need not be. 
 
DEFSTRUCT:  The structure type name must be recognized as a valid type name
in declarations, as for DEFTYPE.  The structure slot accessors must be made
known to SETF.  In addition, further DEFSTRUCT definitions should be able
to :INCLUDE a structure type defined earlier in the file being compiled.
The functions which DEFSTRUCT generates, and the #S reader syntax, may or
may not be available at compile time.

(3) The compile-time side effects may cause information about the
definition to be stored differently than if the defining macro had
been processed in the "normal" way (either interpretively or by loading
the compiled file).

In particular, the information stored by the defining macros at
compile time may or may not be available to the interpreter (either
during or after compilation), or during subsequent calls to COMPILE or
COMPILE-FILE.  For example, the following code is nonportable because
it assumes that the compiler stores the macro definition of FOO where
it is available to the interpreter:

    (defmacro foo (x) `(car ,x))
    (eval-when (eval compile load)
        (print (foo '(a b c))))

A portable way to do the same thing would be to include the macro definition
inside the EVAL-WHEN:

    (eval-when (eval compile load)
        (defmacro foo (x) `(car ,x))
        (print (foo '(a b c))))



Rationale:

The proposal reflects standard programming practices.  The primary
purpose of the proposal is to make an explicit statement that CL
supports the behavior that most programmers expect and many
implementations already provide.


Current Practice:

Many (probably most) Common Lisp implementations, including VaxLisp
and Lucid Lisp, are already largely in conformance.  

In VaxLisp, macro definitions that occur as a side effect of compiling
a DEFMACRO form are available to the compiler (even on subsequent calls
to COMPILE or COMPILE-FILE), but are not available to the interpreter
(even within the file being compiled).
 
Kyoto Common Lisp is a notable offender.  By default, KCL evaluates *all*
top level forms as they are compiled, which is clearly in violation of the
behavior specified on p 69-70 of CLtL.  There is a flag to disable the
compile-time evaluation, but then macros such as DEFMACRO, DEFVAR, etc. do
not make their definitions available at compile-time either.


Cost to implementors:

Making the defining macros expand into EVAL-WHENs to store the required
information is a simple and recommended implementation technique.  The
intent of the proposal is specifically not to require the compiler to
have special knowledge about each of these macros.


Cost to users:

Since CLtL does not specify whether and what compile-time side-effects
happen, any user code which relies on them is, strictly speaking,
nonportable.  In practice, however, most programmers already expect
the behavior described in this proposal and will not find it to be
an incompatible change.


Benefits:

Adoption of the proposal will provide more definite guidelines on how to
write programs that will compile correctly under all CL implementations.


Discussion:

Reaction to an earlier version of this proposal on the CL mailing list was
overwhelmingly positive.

It has been suggested that this proposal should also include PROCLAIM.
However, since PROCLAIM is not a macro, its compile-time side effects
cannot be handled using the EVAL-WHEN mechanism.  A separate proposal
seems more appropriate. 

There has also been a suggestion that DEFCONSTANT should always
evaluate the value provided.  The behavior specified in this proposal
makes DEFCONSTANT similar to DEFVAR and DEFPARAMETER, while allowing
the user to explicitly ask for compile-time evaluation using the #. read
macro.

Item (3) allows for significant deviations between implementations.
While there is some sentiment to the effect that the compiler should
store definitions in a manner identical to that of the interpreter,
other people believe strongly that compiler side-effects should be
completely invisible to the interpreter.  The author is of the opinion
that since this is a controversial issue, further attempts to restrict
this behavior should be considered as separate proposals.

-------

∂24-May-88  1251	CL-Compiler-mailer 	Re: issue DEFINING-MACROS-NON-TOP-LEVEL 
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 24 May 88  12:50:53 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA05361; Tue, 24 May 88 13:50:14 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805241950.AA05361@cs.utah.edu>
Date: Tue, 24 May 88 13:50:13 MDT
Subject: Re: issue DEFINING-MACROS-NON-TOP-LEVEL
To: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>
Cc: "cl-compiler" <cl-compiler@sail.stanford.edu>
In-Reply-To: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>, 23 May 88 14:06:00 EDT

> Date: 23 May 88 14:06:00 EDT
> From: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>
> 
> Except this is still true:
>     (let ((x (f)))
>       (defmacro m (y) `(+ ,x ,y)))
>     ...
>     (defun g (...)
>       ... (m ...) ...)
> and inside G the use of M is an error because it isn't guaranteed to be
> recognized as a call to a macro.

I don't think this follows from our model of how the defining macros
do their thing at compile time, and how EVAL-WHEN works at
non-top-level.  The DEFMACRO presumably would expand into an (EVAL-WHEN
(COMPILE) ...) to store the macro definition for the compiler, and as
long as the compiler processes this before it runs across any calls to
the macro, this example would be OK (that is, if it were not for the
problem of the macro function getting defined in the wrong lexical
environment).

If you want the defining macros to have their compile-time side-effects
occur only if they appear at top-level, I think we have to come up with
some other model to explain how this happens (other than saying that
they expand into EVAL-WHENs).  Do we really want to do that?

-Sandra
-------

∂24-May-88  1623	CL-Compiler-mailer 	new, improved defining macros proposal  
Received: from EDDIE.MIT.EDU by SAIL.Stanford.EDU with TCP; 24 May 88  16:22:56 PDT
Received: by EDDIE.MIT.EDU with UUCP with smail2.5 with sendmail-5.45/4.7 id <AA19899@EDDIE.MIT.EDU>; Tue, 24 May 88 19:20:05 EDT
Received: by spt.entity.com (smail2.5); 24 May 88 18:17:07 EDT (Tue)
To: sandra@cs.utah.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Sandra J Loosemore's message of Tue, 24 May 88 13:37:06 MDT <8805241937.AA04849@cs.utah.edu>
Subject: new, improved defining macros proposal
Message-Id: <8805241817.AA22314@spt.entity.com>
Date: 24 May 88 18:17:07 EDT (Tue)
From: gz@spt.entity.com (Gail Zacharias)

I just started receiving this mailing list, so my apologies if this has been
discussed before.

   DEFCONSTANT: 	...			(If the initial
   value is a constant, however, an implementation is allowed to
   substitute the constant value for references to the named constant
   during subsequent compilation.)

I have a problem with this.  The compiler shouldn't have licence to substitute
for the variable without fully implementing the semantics of DEFCONSTANT.
In particular, under this proposal, would the DEFCONSTANT's with constant
initial values be "evaluable at compile time" in the sense used in the
description of DEFMACRO?  I.e. would the following work?
   	(DEFCONSTANT FOO 'FOO)
	(DEFMACRO FOO () `',FOO)
	(DEFVAR *FOO* (FOO))
In addition, the distinction between constant/non-constant initial value is
artificial and potentially ambiguous in the face of differing constant-folding
capabilities.  Consider
	(DEFCONSTANT FOO 17)
	(DEFCONSTANT BAR (ASH 1 FOO))
Are compilers allowed to substitute for BAR?

I think toplevel DEFCONSTANT should either be treated like DEFMACRO (i.e.
implicitly compile-time: initial value "must be evaluable at compile time" and
the binding must be made available to other compile-time code) or like
DEFVAR/DEFPARAMETER (implicitly load-time: compiler recognizes the variable as
special, but it is not allowed to substitute the value).  I don't have a
strong preference either way (since you can always get "the other" semantics
via eval-when), but I don't like the proposed mixture of the two.

∂25-May-88  0809	CL-Compiler-mailer 	Re: Issue: COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS (version 5)  
Received: from hudson.dec.com by SAIL.Stanford.EDU with TCP; 25 May 88  08:09:31 PDT
Date: 25 May 88 11:06:00 EDT
From: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>
Subject: Re: Issue: COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS (version 5)
To: "cl-compiler" <cl-compiler@sail.stanford.edu>
cc: vanroggen   
Reply-To: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>

I agree with the proposal in its treating the initial value form of
DEFCONSTANT just like those of DEFVAR and DEFPARAMETER in that that form
must not be evaluated at compile time.  (Of course, DEFCONSTANT, just like
the others, may macroexpand into code that evaluates at compile-time.)

However, to answer the concerns of compiler implementors not being able
to make certain optimizations, it's quite permissible for compilers to
"evaluate" constants, both literals such as 3.4 and expressions such as
(ASH 3 7) or even (ASH FOO BAR) if both FOO and BAR were previously
defined DEFCONSTANTS with constant values.  The point is that if the
constant value depends on its run-time environment in any way, the
compiler can't try to do "constant folding" too early unless it can prove
there won't be any difference.

There's a separate issue here regarding substitution of constants, I think,
in whether it's permissible for (DEFCONSTANT FOO "abc") and a later use of
FOO to "copy" the string value.  I'd change the wording about substitution
of constants to mention that that's a separate issue for clean-up.

BTW, in the next-to-last paragraph, using "#." is also the wrong time--
since read-time might well be too early.  It's best to recommend either
that or EVAL-WHEN as needed.

			---Walter
------

∂25-May-88  0926	CL-Compiler-mailer 	Re: new, improved defining macros proposal   
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 25 May 88  09:24:41 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA04830; Wed, 25 May 88 10:24:32 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8805251624.AA04830@cs.utah.edu>
Date: Wed, 25 May 88 10:24:31 MDT
Subject: Re: new, improved defining macros proposal
To: gz@spt.entity.com (Gail Zacharias)
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: gz@spt.entity.com (Gail Zacharias), 24 May 88 18:17:07 EDT (Tue)

Sigh, this issue just won't go away.

What one would normally expect DEFCONSTANT to do is to setq the symbol
and then somehow mark it as being constant, so that it can't be setq'ed
again.  At compile-time, if the value-form is not evaluable, you
obviously can't setq it yet.  I agree it would be silly to specify
that the setq'ing happens at compile-time in some cases but not in
others, and that was certainly not what I had in mind.

The intention was that *if* the compiler does substitution of symbolic
constants with their values *and* it can determine the value of the
symbolic constant at compile-time, *then* the compiler can assume
that the value of the constant at run-time is the same as what it sees
at compile-time and go ahead and make a substitution for it.  I would
assume that if an implementation is sophisticated enough to do all of
this, it would be able to store the information about the constant value
using some other mechanism besides setq'ing the symbol at compile-time.

I can try rewording this part of the proposal yet again.  I think the
main points are:

(1) the compiler should know that the symbol is a constant so it will
not complain when it sees references to it as an unbound variable, and
possibly so it will complain when it sees attempts to setq or bind the
symbol.

(2) neither the evaluation of the value-form or the setq'ing of the
symbol may happen at compile-time (analagous to DEFVAR and DEFPARAMETER)

(3) if the value-form can be evaluated at compile-time, the compiler may
assume that the constant will have the same value at run-time.

-Sandra
-------

∂27-May-88  0828	CL-Compiler-mailer 	Re: Issue: EVAL-WHEN-NON-TOP-LEVEL 
Received: from hudson.dec.com by SAIL.Stanford.EDU with TCP; 27 May 88  08:28:08 PDT
Date: 27 May 88 11:15:00 EDT
From: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>
Subject: Re: Issue: EVAL-WHEN-NON-TOP-LEVEL
To: "cl-compiler" <cl-compiler@sail.stanford.edu>
cc: vanroggen   
Reply-To: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>

There really isn't enough consideration of what happens when the
EVAL-WHEN isn't a top-level, and what following expressions may
depend on from what was inside a non-top-level EVAL-WHEN.

The problem is what order expressions may get "processed", particularly
by code-walkers such as compilers.

Here's a simple example which assumes the DEFMACRO expands into an
(EVAL-WHEN ...) to tell everyone who cares (particularly the compiler at
compile time) that M is a macro.

  (let ...
    (defmacro m ...)
    (m ...))

But the body of the LET is equivalent to

  (let ...
    (flet ((rest () (m ...)))
      (defmacro m ...)
      (rest)))

which isn't going to work.

The easiest solution is to assume that one cannot depend on the effects
of the EVAL-WHEN at compile time until the next top-level form.

			---Walter
------

∂09-Jun-88  0921	CL-Compiler-mailer 	Compiler Subcommittee meeting 
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 9 Jun 88  09:21:34 PDT
Received: by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA01037; Thu, 9 Jun 88 09:20:22 PDT
Received: by franz (3.2/3.14)
	id AA02004; Thu, 9 Jun 88 08:02:11 PDT
Received: by feast (5.5/3.14)
	id AA00828; Thu, 9 Jun 88 10:32:54 EDT
Date: Thu, 9 Jun 88 10:32:54 EDT
From: franz!feast!smh@ucbarpa.Berkeley.EDU (Steven M. Haflich)
Message-Id: <8806091432.AA00828@feast>
To: franz!sail.stanford.edu!cl-compiler
Subject: Compiler Subcommittee meeting

Owing to the difficulty in scheduling conference rooms at Symbolics in
the evening, our subcommittee will meet at:

	Tuesday, June 14, 7:30 PM

	Gigamos
	675 Massachusetts Avenue
	Cambridge MA

Gigamos is on the 7th floor of a large office building which is a mere
few steps from the MBTA Central Square Red Line stop, or about a 20
minute walk from Harvard Square, Symbolics, or MIT.  There is a
security guard who should allow you to sign in by mentioning Gigamos,
but if there is any difficulty, call Gigamos from the lobby at
876-6819 and ask for me.

Please RSVP so we can know who's coming and when it's safe to start.

If anyone would like to meet for dinner beforehand (or afterhand) that
would be just dandy.  There are a multitude of superb ethnic
establishments in the immediate neighborhood.

∂09-Jun-88  1219	CL-Compiler-mailer 	Compiler Subcommittee meeting 
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 9 Jun 88  12:19:27 PDT
Received: by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA04525; Thu, 9 Jun 88 12:18:16 PDT
Received: by franz (3.2/3.14)
	id AA02522; Thu, 9 Jun 88 11:24:12 PDT
Received: from TI.COM by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA02196; Thu, 9 Jun 88 10:29:10 PDT
Received: by ti.com id AA04276; Thu, 9 Jun 88 12:28:03 CDT
Received: from mips by tilde id AA15746; Thu, 9 Jun 88 12:25:12 CDT
Received: by mips id AA09228; Thu, 9 Jun 88 12:25:03 CDT
Date: Thu, 9 Jun 88 12:25:03 CDT
From: David Bartley <franz!ucbarpa!mips.csc.ti.com!bartley@ucbarpa.Berkeley.EDU>
Message-Id: <8806091725.AA09228@mips>
To: franz!feast!smh
Cc: franz!sail.stanford.edu!cl-compiler
In-Reply-To: "Steven M. Haflich"'s message of Thu, 9 Jun 88 10:32:54 EDT <8806091432.AA00828@feast>
Subject: Compiler Subcommittee meeting

> Please RSVP so we can know who's coming and when it's safe to start.

I expect to make it.

∂09-Jun-88  1346	CL-Compiler-mailer 	Re: Compiler Subcommittee meeting  
Received: from NSS.Cs.Ucl.AC.UK by SAIL.Stanford.EDU with TCP; 9 Jun 88  13:41:27 PDT
Received: from aiai.edinburgh.ac.uk by NSS.Cs.Ucl.AC.UK   via Janet with NIFTP
           id aa09118; 9 Jun 88 21:31 BST
From: Jeff Dalton <jeff%aiai.edinburgh.ac.uk@NSS.Cs.Ucl.AC.UK>
Date: Thu, 9 Jun 88 21:31:12 BST
Message-Id: <17148.8806092031@aiai.ed.ac.uk>
To: cl-compiler@sail.stanford.edu
Subject: Re: Compiler Subcommittee meeting

> Please RSVP so we can know who's coming and when it's safe to start.

I'd mail to you directly, but there's just no hope of figuring
out what magic incantations are necessary to reach

	edu.berkeley.ucbarpa!franz!feast!smh

from here.

> There are a multitude of superb ethnic establishments

Good idea.

Jeff Dalton,                      JANET: J.Dalton@uk.ac.ed             
AI Applications Institute,        ARPA:  J.Dalton%uk.ac.ed@nss.cs.ucl.ac.uk
Edinburgh University.             UUCP:  ...!ukc!ed.ac.uk!J.Dalton

∂09-Jun-88  1415	CL-Compiler-mailer 	(another) revised version of the defining macros proposal   
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 9 Jun 88  14:14:47 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA12037; Thu, 9 Jun 88 14:41:41 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8806092041.AA12037@cs.utah.edu>
Date: Thu, 9 Jun 88 14:41:39 MDT
Subject: (another) revised version of the defining macros proposal
To: cl-compiler@sail.stanford.edu

Here is yet another revision to the defining macros proposal.  The only
thing that has changed is the wording of the DEFCONSTANT section.  I hope
that this time I have at least managed to make the language concise enough
so that we can agree on what it says, even if we don't all agree *with*
what it says.

-Sandra


Issue:		COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS
References:	CLtL pages 66-70, 143
Category:	CLARIFICATION
Edit history:   V1, 07 Oct 1987 Sandra Loosemore
                V2, 15 Oct 1987 Sandra Loosemore
                V3, 15 Jan 1988 Sandra Loosemore
		V4, 06 May 1988 Sandra Loosemore
		V5, 20 May 1988 Sandra Loosemore
		V6, 09 Jun 1988 Sandra Loosemore


Problem Description:

Standard programming practices assume that, when calls to defining
macros such as DEFMACRO and DEFVAR are processed by COMPILE-FILE,
certain side-effects occur that affect how subsequent forms in the
file are compiled.  However, these side-effects are not mentioned in
CLtL, except for a passing mention that macro definitions must be
``seen'' by the compiler before it can compile calls to those macros
correctly.  In order to write portable programs, users must know
exactly which defining macros have compile-time side-effects and what
those side-effects are. 

Inter-file compilation dependencies are distinct from, and not
addressed by, this issue. 


Proposal: COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY

(1) Clarify that defining macros such as DEFMACRO or DEFVAR, appearing
within a file being processed by COMPILE-FILE, normally have
compile-time side effects which affect how subsequent forms in the
same file are compiled.  A convenient model for explaining how these
side effects happen is that the defining macro expands into one or
more EVAL-WHEN forms, and that the calls which cause the compile-time
side effects to happen appear in the body of an (EVAL-WHEN (COMPILE)
...) form.  This is also the recommended implementation technique. 

(2) The affected defining macros and their specific side effects are
as follows:
 
DEFTYPE: The body of a DEFTYPE form must be evaluable at compile time.
If the expansion of a DEFTYPE'd type specifier is also a valid type
specifier at compile time, then the DEFTYPE'd type specifier is also
considered to be fully defined at compile time and must be recognized
within subsequent type declarations. 

DEFMACRO, DEFINE-MODIFY-MACRO:  Macro definitions must be stored at compile
time, so that occurences of the macro later on in the file will be expanded
correctly.  The body of the macro (but not necesarily its expansion) must 
be evaluable at compile time.
 
DEFUN: An implementation may choose to store information about the
function for the purposes of compile-time error-checking (such as
checking the number of arguments on calls), or to enable the function
to be expanded inline.  Portable code should not rely on DEFUN making
the function definition available at compile time.
 
DEFVAR, DEFPARAMETER: The compiler must recognize that the variables
named by these forms have been proclaimed special.  The initial value
form must not be evaluated at compile time. 
 
DEFCONSTANT: The compiler must recognize the symbol as being constant
(for example, to suppress warnings about references to the symbolic
constant as an unbound variable or to enable warnings about binding or
SETQ'ing the constant in the code being compiled).  Neither evaluation
of the value-form or SETQ'ing of the symbol may occur at compile-time.
However, if the (unevaluated) value-form is CONSTANTP, the compiler is
allowed to build assumptions about the value of the constant into
programs being compiled, as described on p. 68-69 of CLtL.
 
DEFSETF, DEFINE-SETF-METHOD: SETF methods must be available during the
expansion of calls to SETF later on in the file.  The body of
DEFINE-SETF-METHOD and the complex form of DEFSETF must be evaluable
at compile time, although the expansions need not be. 
 
DEFSTRUCT:  The structure type name must be recognized as a valid type name
in declarations, as for DEFTYPE.  The structure slot accessors must be made
known to SETF.  In addition, further DEFSTRUCT definitions should be able
to :INCLUDE a structure type defined earlier in the file being compiled.
The functions which DEFSTRUCT generates, and the #S reader syntax, may or
may not be available at compile time.

(3) The compile-time side effects may cause information about the
definition to be stored differently than if the defining macro had
been processed in the "normal" way (either interpretively or by loading
the compiled file).

In particular, the information stored by the defining macros at
compile time may or may not be available to the interpreter (either
during or after compilation), or during subsequent calls to COMPILE or
COMPILE-FILE.  For example, the following code is nonportable because
it assumes that the compiler stores the macro definition of FOO where
it is available to the interpreter:

    (defmacro foo (x) `(car ,x))
    (eval-when (eval compile load)
        (print (foo '(a b c))))

A portable way to do the same thing would be to include the macro definition
inside the EVAL-WHEN:

    (eval-when (eval compile load)
        (defmacro foo (x) `(car ,x))
        (print (foo '(a b c))))



Rationale:

The proposal reflects standard programming practices.  The primary
purpose of the proposal is to make an explicit statement that CL
supports the behavior that most programmers expect and many
implementations already provide.


Current Practice:

Many (probably most) Common Lisp implementations, including VaxLisp
and Lucid Lisp, are already largely in conformance.  

In VaxLisp, macro definitions that occur as a side effect of compiling
a DEFMACRO form are available to the compiler (even on subsequent calls
to COMPILE or COMPILE-FILE), but are not available to the interpreter
(even within the file being compiled).
 
Kyoto Common Lisp is a notable offender.  By default, KCL evaluates *all*
top level forms as they are compiled, which is clearly in violation of the
behavior specified on p 69-70 of CLtL.  There is a flag to disable the
compile-time evaluation, but then macros such as DEFMACRO, DEFVAR, etc. do
not make their definitions available at compile-time either.


Cost to implementors:

Making the defining macros expand into EVAL-WHENs to store the required
information is a simple and recommended implementation technique.  The
intent of the proposal is specifically not to require the compiler to
have special knowledge about each of these macros.


Cost to users:

Since CLtL does not specify whether and what compile-time side-effects
happen, any user code which relies on them is, strictly speaking,
nonportable.  In practice, however, most programmers already expect
the behavior described in this proposal and will not find it to be
an incompatible change.


Benefits:

Adoption of the proposal will provide more definite guidelines on how to
write programs that will compile correctly under all CL implementations.


Discussion:

Reaction to an earlier version of this proposal on the CL mailing list was
overwhelmingly positive.

It has been suggested that this proposal should also include PROCLAIM.
However, since PROCLAIM is not a macro, its compile-time side effects
cannot be handled using the EVAL-WHEN mechanism.  A separate proposal
seems more appropriate. 

There has also been a suggestion that DEFCONSTANT should always
evaluate the value provided.  The behavior specified in this proposal
makes DEFCONSTANT similar to DEFVAR and DEFPARAMETER, while allowing
the user to explicitly ask for compile-time evaluation using the #. read
macro.

Item (3) allows for significant deviations between implementations.
While there is some sentiment to the effect that the compiler should
store definitions in a manner identical to that of the interpreter,
other people believe strongly that compiler side-effects should be
completely invisible to the interpreter.  The author is of the opinion
that since this is a controversial issue, further attempts to restrict
this behavior should be considered as separate proposals.

-------

∂09-Jun-88  1414	CL-Compiler-mailer 	(another) new version of the non-top-level defining macros proposal   
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 9 Jun 88  14:14:37 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA12308; Thu, 9 Jun 88 14:46:03 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8806092046.AA12308@cs.utah.edu>
Date: Thu, 9 Jun 88 14:46:03 MDT
Subject: (another) new version of the non-top-level defining macros proposal
To: cl-compiler@sail.stanford.edu

Item 5 is new, from a suggestion by Walter.  I haven't gotten comments from
anyone else on the previous version of this proposal.

-Sandra



Issue:		DEFINING-MACROS-NON-TOP-LEVEL
References:	CLtL p. 66-70, 143
		Issue EVAL-WHEN-NON-TOP-LEVEL
		Issue COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS
Category:	CLARIFICATION, ENHANCEMENT
Edit History:   6-May-88, V1 by Sandra Loosemore
		9-Jun-88, V2 by Sandra Loosemore


Problem Description:

CLtL leaves the interpretation of defining forms such as DEFMACRO and
DEFVAR that appear in other than top-level locations unspecified.
Resolution of other issues (EVAL-WHEN-NON-TOP-LEVEL and
COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS) now allows reasonable
semantics to be assigned to defining forms which appear at
non-top-level.


Proposal: DEFINING-MACROS-NON-TOP-LEVEL:ALLOW

(1) Clarify that while defining macros normally appear at top level,
it is meaningful to place them in non-top-level contexts and that the
compiler must handle them properly in all situations.  Remove the
language on p. 66 of CLtL which states that the compiler is not
required to recognize defining macros at other than top-level.

(2) The proposal COMPILE-FILE-HANDLING-OF-TOP-LEVEL-FORMS:CLARIFY
defines a model for specifying how defining macros work.  To
summarize, the expansion of the macro (rather than its expander
function) is responsible for storing information about the definition.
Compile-time side effects are typically handled by including one or
more EVAL-WHEN forms in the expansion.  A compiler may choose
some other implementation, such as treating defining macros as
implementation-specific special forms, provided that the semantics
are compatible.

(3) Defining macros which define functional objects (such as DEFUN and
DEFMACRO) must ensure that the functions are defined in the lexical
environment in which the defining macro appears.  In the model
referred to above, this would normally be implemented by producing a
FUNCTION special form in the macro expansion.  For example, the
following code causes the function BAR to be closed over the variable
X:

    (let ((x  (some-hairy-computation)))
        (defun bar (y) (+ x y)))

(4) The language on p. 145 of CLtL, which states that macro functions
are defined in the null lexical environment, should be removed.
Instead, defining forms such as DEFMACRO which make a functional
definition available at the compile time use the environment must
normally appear inside an explicit (EVAL-WHEN (COMPILE) ...) to ensure
that the correct lexical environment is seen. 

An example may help clarify why this is necessary.  The code fragment

    (let ((x  (some-hairy-computation)))
        (defmacro bar-macro (y) `(+ ,x ,y)))

would macroexpand into something similar to

    (let ((x  (some-hairy-computation)))
        (eval-when (eval compile load)
            (setf (macro-function 'bar-macro) 
	          #'(lambda (form env)
		        (let ((y  (second form)))
			    `(+ ,x ,y))))
            'bar-macro))

Since the rules for (EVAL-WHEN (COMPILE) ...) state that evaluation
takes place in the null lexical environment, in this situation X would
be treated as a special variable within the macro function.  However,
in the EVAL or LOAD situations, the lexical value of X would be used.
To ensure consistency, the correct definition would be:

    (eval-when (eval compile load)
        (let ((x  (some-hairy-computation)))
            (defmacro bar (y) `(+ ,x ,y))))


(5) Clarify that ``top-level forms'' are evaluable data objects read
in from an input source (such as a keyboard or disk file) by
successive calls to the function READ.  As a special case, forms
within a top-level PROGN are also considered to be top-level forms.
Specify that top-level forms in a file being compiled are guaranteed
to be processed sequentially, but the order in which subforms of a
top-level form are processed by the compiler is explicitly left
unspecified.  It is an error for user code to depend upon the
compile-time side-effects of a defining macro within the same
top-level form in which the defining macro appears.


Rationale:

The notion of a ``top-level form'' is rather confused, since the term
is used in CLtL to refer both to a place where a form may appear (what
this proposal continues to call ``top-level''), and to instances of
forms which traditionally appear there (what this proposal calls
``defining macros'').  

There has been a suggestion that the notion of a top-level form should
be extended to include forms in the body of a top-level LET, to allow
forms such as DEFUN to be meaningful there.  However, we feel that a
cleaner solution is to remove the restrictions on the placement of
defining macros altogether. 


Current Practice:


Cost to implementors:


Cost to users:

None.  This is a compatible extension.


Benefits:

The notion of defining macros as being somehow special is removed from
the language.  Allowing defining macros to appear anywhere instead of
restricting them to certain positions results in a cleaner language
design.


Discussion:

-------

∂09-Jun-88  1707	CL-Compiler-mailer 	next order of business   
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 9 Jun 88  17:07:34 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA17668; Thu, 9 Jun 88 18:06:36 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8806100006.AA17668@cs.utah.edu>
Date: Thu, 9 Jun 88 18:06:34 MDT
Subject: next order of business
To: cl-compiler@sail.stanford.edu

It seems like issues relating to the treatment of constants in compiled
code, which have been discussed on the common-lisp mailing list for the
past few weeks, should probably be the next thing we try to address.  I
believe that the main thing that has to be done here is to explicitly
state that it is an error to destructively modify structured constants
(since the current wording in CLtL allows the compiler to collapse EQUAL
structures), and to clarify exactly what kinds of destructive operations
would be forbidden.  For example, I do not believe we would want to
prohibit alteration of the "fields" of a quoted symbol such as the
property list.  There are other, more radical approaches we could
take -- such as forbidding implementations to collapse constants or put
them in read-only storage -- but I don't know if any of these would get
much support.  Comments, anyone?  I could try to sketch out a proposal
on this over the weekend and bring it to Cambridge for discussion.

-Sandra
-------

∂10-Jun-88  0121	CL-Compiler-mailer 	Compiler Subcommittee meeting and dinner
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 10 Jun 88  01:21:25 PDT
Received: by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA21348; Fri, 10 Jun 88 01:20:10 PDT
Received: by franz (3.2/3.14)
	id AA04504; Fri, 10 Jun 88 00:59:42 PDT
Received: by feast (5.5/3.14)
	id AA00493; Fri, 10 Jun 88 03:50:35 EDT
Date: Fri, 10 Jun 88 03:50:35 EDT
From: franz!feast!smh@ucbarpa.Berkeley.EDU (Steven M. Haflich)
Message-Id: <8806100750.AA00493@feast>
To: franz!sail.stanford.edu!cl-compiler
Subject: Compiler Subcommittee meeting and dinner

There have been a couple positive replies.  I propose that people who
want to go to dinner on Tuesday meet at Gigamos at 6PM.  We can wait
there until about 6:15, walk to dinner in the neighborhood, and return
to Gigamos around 7:30.  We'll try to leave word with the guard where
we go to dinner in case someone is late.

Once again, Gigamos is at Central Square Cambridge, 675 Massachusetts
Avenue, the 7th floor of the "Tofias" building.  The security guard
should allow access if you mention Gigamos, but if there is any
problem call 876-6819 and ask for me.  I'll try to leave a list of
subcommittee members with the guard.

∂19-Jun-88  1717	Common-Lisp-mailer 	#, read macro  
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 19 Jun 88  17:17:02 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA01138; Sun, 19 Jun 88 18:15:26 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8806200015.AA01138@cs.utah.edu>
Date: Sun, 19 Jun 88 18:15:25 MDT
Subject: #, read macro
To: common-lisp@sail.stanford.edu, cl-compiler@sail.stanford.edu

One of the items currently before the X3J13 compiler cleanup
subcommittee is tightening up the definition of how the #, (sharp-sign
comma) read macro should work, and where it may legitimately appear in
code to be compiled.  We are considering (among other options) removing
it from Common Lisp entirely.  Since this would clearly be an
incompatible change to the language, we would like to hear from people
who actually use #, to find out how it is being used and whether some
other technique(s) couldn't be used to solve the same problems.  

Please send replies on this subject to cl-compiler@sail.stanford.edu.

-Sandra
-------

∂19-Jun-88  2355	CL-Compiler-mailer 	#, read macro  
Received: from MCC.COM by SAIL.Stanford.EDU with TCP; 19 Jun 88  23:55:46 PDT
Received: from PELE.ACA.MCC.COM by MCC.COM with TCP/SMTP; Mon 20 Jun 88 01:53:45-CDT
Date: Mon, 20 Jun 88 01:52 CDT
From: Christopher Maeda <maeda@MCC.COM>
Subject: #, read macro
To: sandra@cs.utah.edu, common-lisp@sail.stanford.edu, cl-compiler@sail.stanford.edu
cc: bug-cyc@MCC.COM
In-Reply-To: <8806200015.AA01138@cs.utah.edu>
Message-ID: <19880620065222.1.MAEDA@PELE.ACA.MCC.COM>

We are implementing a frame system where each frame is a defstruct.  We
use a reader macro to reference case sensitive frame names, permitting
the frame namespace to be disjoint from the symbol namespace.  The
reader macro also lets us hook into a completion package that is very
handy for longer names.

I would be interested in hearing what alternatives the cleanup committee
is considering.  Being able to dispatch to an arbitrary read function is
hard to beat.

--Chris

∂20-Jun-88  1006	Common-Lisp-mailer 	#, read macro  
Received: from Think.COM by SAIL.Stanford.EDU with TCP; 20 Jun 88  10:06:29 PDT
Return-Path: <barmar@Think.COM>
Received: from sauron.think.com by Think.COM; Mon, 20 Jun 88 13:11:08 EDT
Received: from OCCAM.THINK.COM by sauron.think.com; Mon, 20 Jun 88 13:11:05 EDT
Date: Mon, 20 Jun 88 13:03 EDT
From: Barry Margolin <barmar@Think.COM>
Subject: #, read macro
To: Christopher Maeda <maeda@mcc.com>
Cc: sandra@cs.utah.edu, common-lisp@sail.stanford.edu,
        cl-compiler@sail.stanford.edu, bug-cyc@mcc.com
In-Reply-To: <19880620065222.1.MAEDA@PELE.ACA.MCC.COM>
Supersedes: <19880620170243.2.BARMAR@OCCAM.THINK.COM>
Message-Id: <19880620170302.3.BARMAR@OCCAM.THINK.COM>

    Date: Mon, 20 Jun 88 01:52 CDT
    From: Christopher Maeda <maeda@mcc.com>

    We are implementing a frame system where each frame is a defstruct.  We
    use a reader macro to reference case sensitive frame names, permitting
    the frame namespace to be disjoint from the symbol namespace.  The
    reader macro also lets us hook into a completion package that is very
    handy for longer names.

    I would be interested in hearing what alternatives the cleanup committee
    is considering.  Being able to dispatch to an arbitrary read function is
    hard to beat.

    --Chris

No one is talking about removing reader macros in general.  We are
considering removing the "#," reader macro.  "#," is a relatively
obscure cousin of "#."; it causes the form following it to be
evaluated at load time rather than at read time as "#." does.

To see how it currently works, put the following definition in a file:

(defun sharp-comma-example ()
  (quote #,*sharp-comma-var*))

Compile the file, type (setq *sharp-comma-var* 'a), then load the binary
file.  Then type (setq *sharp-comma-var* 'b) and (sharp-comma-example).
It should return A.


                                                barmar

∂20-Jun-88  1237	CL-Compiler-mailer 	Re: #, read macro   
Received: from gremlin.nrtc.northrop.com by SAIL.Stanford.EDU with TCP; 20 Jun 88  12:37:05 PDT
Received: from tribble by gremlin.nrtc.northrop.com id a018817;
          20 Jun 88 12:22 PDT
To: Sandra J Loosemore <sandra@cs.utah.EDU>
cc: common-lisp@sail.stanford.EDU, cl-compiler@sail.stanford.EDU, 
    jbarnett@gremlin.nrtc.northrop.COM
Subject: Re: #, read macro 
In-reply-to: Your message of Sun, 19 Jun 88 18:15:25 -0600.
             <8806200015.AA01138@cs.utah.edu> 
Date: Mon, 20 Jun 88 12:22:53 -0700
From: jbarnett@gremlin.nrtc.northrop.COM

One use of this construct is to simulate ALGOL-like OWN variables; to wit:
  (defun foo (arg ... &aux (var '#,<complex expression>))
      body that references var...)
where the <complex expression> is computed in terms of previously defined
defvars, defuns, etc., and you don't want to create yet another only-used-in
one-place special variable, e.g.,
  (defvar *foos-own* <complex expression>)
  (defun foo (args ...)
      body that reference *foos-own* insteadof var...)
By the way, there's not much use to trying to clean up the use of #, until
you do a better job of defining EVAL-WHEN (or whatever you call it now).
If you do that properly, not only will #, be easy to understand, implement, and
use, but I'd guess that several natural and useful extentions will occur.

	Jeff

∂20-Jun-88  1706	CL-Compiler-mailer 	#,   
Received: from labrea.stanford.edu by SAIL.Stanford.EDU with TCP; 20 Jun 88  17:06:24 PDT
Received: by labrea.stanford.edu; Mon, 20 Jun 88 17:04:59 PDT
Received: from atlantis.lucid.com by edsel id AA16965g; Mon, 20 Jun 88 17:00:49 PDT
Received: by atlantis id AA00092g; Mon, 20 Jun 88 17:00:08 pdt
Date: Mon, 20 Jun 88 17:00:08 pdt
From: Leonard Zubkoff <edsel!lnz@labrea.stanford.edu>
Message-Id: <8806210000.AA00092@atlantis.lucid.com>
To: cl-compiler@sail.stanford.edu
Subject: #,

The only time I've ever used #, is the following one instance:

(defconstant program-version #,(form-to-decide-what-the-version-should-be))

The reason I needed to do this is that:

(1) I wanted the version to be decided at the time I loaded the above form.
(2) The form resides in a compiled file.
(3) I wanted a constant, not a variable.

		Leonard

∂20-Jun-88  2022	CL-Compiler-mailer 	non-top-level DEFUN 
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 20 Jun 88  20:22:48 PDT
Received: by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA00876; Mon, 20 Jun 88 20:21:01 PDT
Received: by franz (3.2/3.14)
	id AA00293; Mon, 20 Jun 88 19:45:39 PDT
Received: by feast (5.5/3.14)
	id AA00094; Mon, 20 Jun 88 22:36:10 EDT
Date: Mon, 20 Jun 88 22:36:10 EDT
From: franz!feast!smh@ucbarpa.Berkeley.EDU (Steven M. Haflich)
Message-Id: <8806210236.AA00094@feast>
To: franz!sail.stanford.edu!cl-compiler
Subject: non-top-level DEFUN

Perhaps I've been on another planet, but I just realized a serious
problem with non-top-level function-defining DEF* forms.

Our interpreter will already handle the following without problem:

(let ((*foo* 3))
  (defun set-foo (x) (setq *foo* x))
  (defun get-foo (y) (cons *foo* y)))

So will our COMPILE-FILE.  The problem comes when the above forms are
entered interpreted and subsequently a (COMPILE 'GET-FOO) is executed.
Interpreted and compiled closures have entirely different
representation, and it is impossible for compiled and interpreted
functions to share a closure.  It would appear that the original CLtL
rules on closures and compilation are designed to permit this freedom,
although use of (SETF (SYMBOL-FUNCTION XXX #'(...))) can obviously
create named interpreted closure functions which subsequently one
could attempt to compile.  No one has yet complained ...

I wonder if any other implementations will suffer the same problem?
Has anyone yet thought about this?  Is the non-top-level-defun change
less compatible than we thought?  Obviously, the compiler and
interpreter could be unified, but efficiency might suffer.

∂20-Jun-88  2208	CL-Compiler-mailer 	#, read macro  
Received: from ECLA.USC.EDU by SAIL.Stanford.EDU with TCP; 20 Jun 88  22:08:18 PDT
Date: Mon 20 Jun 88 13:16:31-PDT
From: Kim A. Barrett <IIM@ECLA.USC.EDU>
Subject: #, read macro
To: cl-compiler@SAIL.STANFORD.EDU
cc: iim@ECLA.USC.EDU
Message-ID: <12408021267.27.IIM@ECLA.USC.EDU>

    While I admit that the uses of #, are pretty esoteric, I don't think that
is sufficient reason to flush it, unless you can really convince everybody that
ALL possible uses can be handled equally well in some other way.

    The places I've seen it used where I thought it was justified have all
essentially been instances of caching.  The most common cases have involved
using #, to cache the result of the search for some special object, when the
search can't be performed at compile time.  I've also seen it used to create a
data structure once, in order to avoid consing, although this practice is
usually pretty questionable, due to multi-tasking considerations.  This kind of
usage can probably be handled about equally well by using defparameter.  There
are a couple of possible disadvantages to using defparameter though.  First, It
sort of adds to clutter, since you need to think up a name for each case of #,
(although this isn't always a bad thing), and conses up a symbol, which
requires memory.  Second, a special variable lookup might be slower than
accessing an inline constant in a given implementation; I don't thing the
reverse is very likely.  Also, using a defparameter means that someone could
change its value, though this could actually be a blessing when debugging.

    Another place where I've seen it used is to produce some unique value once
(to avoid consing), for use as the default argument to get/getf, or the eof
value for read, and similar things.  In this case it is the uniqueness of the
value (testable with EQ) that is important, which makes the defparameter
solution more likely to get broken by having someone come along and
inappropriately bash the variable.  However, it is usually (I'm reluctant to
say always) the case that this idiom can be handled using #. instead of #,.

    PCL uses a macro called load-time-eval.  It used to be the case that this
really was trying to use load-time considerations, and not just caching the
result of some computation after the first time it was done.  This macro was
supposed to be sort of an extension of #,, since the people working on PCL
considered the latter to be inadequate for what they were trying to do (which,
in fact, it is).  I believe that PCL no longer actually needs the load-time
specialness, and might in fact be better off using a caching scheme instead.  I
do know that the old PCL code in which I first saw load-time-eval was in fact
rather broken.

    Hmmm.  It seems that while I had initially intended to argue for keeping
it, while writing this I've just about convinced myself that #, can be flushed.
Well, maybe someone else can come up with an excuse for keeping it.

kab

PS. Is this list (cl-compiler) active and significantly disjoint from the main
common-lisp mailing list.  If so, I'd like to be added to it.
-------

∂21-Jun-88  0619	CL-Compiler-mailer 	Re: non-top-level DEFUN  
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 21 Jun 88  06:19:06 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA13810; Tue, 21 Jun 88 07:18:53 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8806211318.AA13810@cs.utah.edu>
Date: Tue, 21 Jun 88 07:18:52 MDT
Subject: Re: non-top-level DEFUN
To: franz!feast!smh@ucbarpa.berkeley.edu (Steven M. Haflich)
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: franz!feast!smh@ucbarpa.Berkeley.EDU (Steven M. Haflich), Mon, 20 Jun 88 22:36:10 EDT

Well, I did specifically ask about things like this for the current
practice section of the proposal....  As far as I know, there probably
isn't any implementation that is strictly in compliance with the
proposal. Some are just more broken than others -- I've heard that in
Symbolics CL DEFUN will refuse to create a closure at all, for example,
and in KCL the compiler expands a DEFUN at top level into something
completely different than a DEFUN anywhere else.  So yes, I expect
implementors are going to have to make some changes to support this, but
there's no such thing as a free lunch.

-Sandra
-------

∂21-Jun-88  0628	CL-Compiler-mailer 	Re: non-top-level DEFUN  
Received: from multimax.ARPA by SAIL.Stanford.EDU with TCP; 21 Jun 88  06:28:34 PDT
Received:  by multimax.ARPA (5.51/25-eef)
	id AA01697; Tue, 21 Jun 88 09:26:21 EDT
Received: from localhost by mist.UUCP (3.2/4.7)
	id AA05487; Tue, 21 Jun 88 09:30:23 EDT
Message-Id: <8806211330.AA05487@mist.UUCP>
To: franz!feast!smh%ucbarpa.Berkeley.EDU@multimax (Steven M. Haflich)
Cc: cl-compiler%sail.stanford.edu@multimax.ARPA
Subject: Re: non-top-level DEFUN 
In-Reply-To: Your message of Mon, 20 Jun 88 22:36:10 -0400.
             <8806210236.AA00094@feast> 
Date: Tue, 21 Jun 88 09:30:20 EDT
From: Dan L. Pierson <pierson%mist@multimax.ARPA>

    I wonder if any other implementations will suffer the same problem?
    Has anyone yet thought about this?  Is the non-top-level-defun change
    less compatible than we thought?  Obviously, the compiler and
    interpreter could be unified, but efficiency might suffer.
    
Kent pointed this out to me at Fort Collins.  The underlying problem
is that if you wrap a closure around a set of top-level forms, you
have to treat the set as a whole for the purpose of compilation.  

I think that it's basically a development environment problem.  An
implementation that wishes to support incremental development in this
style needs to provide a lexical environment inspector.  To RE-compile
one part of a closure, you enter the closure environment and do the
recompile there.  Many Scheme systems support such an inspector,
though none that I'm aware of advertise incremental compilation
(T/ORBIT supports it undocumented, but maybe not this feature).  A
couple of caveats to this suggestion:

    1. It may still be necessary for the entire closure to be either
       compiled or interpreted because of environment representation.

    2. I am not suggesting making this part of the Common Lisp
       standard because we haven't defined what lexical environments
       are yet.  This is about a possible Common Lisp extension that a
       vendor could support; other vendors could just require you to
       redefine the entire closure at once, which probably means file
       compilation (though it would be nice to get a handle on the LET
       and some way to pass it to COMPILE).

All in all, the top level defining forms stuff provides additional
necessary support to an area that Common Lisp copied from Scheme.  The
additional support is useful but not complete; however complete
support would have to include a good deal of development environment
support which is out of our area.

∂21-Jun-88  0637	CL-Compiler-mailer 	Re: non-top-level DEFUN  
Received: from hudson.dec.com by SAIL.Stanford.EDU with TCP; 21 Jun 88  06:36:59 PDT
Date: 21 Jun 88 09:15:00 EDT
From: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>
Subject: Re: non-top-level DEFUN
To: "cl-compiler" <cl-compiler@sail.stanford.edu>
cc: vanroggen   
Reply-To: "AITG::VANROGGEN" <vanroggen%aitg.decnet@hudson.dec.com>

VAX LISP has the same restriction, for the same reason.  However,
the restriction isn't a necessary one, if one is willing to compile
references to free variables with a call to a function to find the
right binding in either the interpreted environment or the compiled
environment as necessary.

This implementation "workaround" would also require the compiler to leave
behind enough information so the interpreter could look up bindings in
the compiled environment.

			---Walter
------

∂21-Jun-88  0721	CL-Compiler-mailer 	Re: non-top-level DEFUN  
Received: from FRED.SLISP.CS.CMU.EDU by SAIL.Stanford.EDU with TCP; 21 Jun 88  07:21:45 PDT
Received: from FRED.SLISP.CS.CMU.EDU by FRED.SLISP.CS.CMU.EDU; 21 Jun 88 10:21:41 EDT
To: cl-compiler@sail.stanford.edu
Subject: Re: non-top-level DEFUN 
Date: Tue, 21 Jun 88 10:21:22 EDT
From: Rob.MacLachlan@WB1.CS.CMU.EDU



In the past, A contingent at Symbolics offered this as an objection to
non-top-level DEFUNs, but nobody else seemed to buy it.  Yes COMPILE will
choke on functions defined in a non-null environment.  No, this does not
prevent incremental development, since in any reasonable incremental
development environment, you will hardly ever use COMPILE.

In your example, in our environment, I would compile the entire LET
together with both DEFUNs by using the editor "Compile Defun" command.

  Rob

∂21-Jun-88  0753	CL-Compiler-mailer 	#, implementation   
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 21 Jun 88  07:53:24 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA15752; Tue, 21 Jun 88 08:53:18 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8806211453.AA15752@cs.utah.edu>
Date: Tue, 21 Jun 88 08:53:15 MDT
Subject: #, implementation
To: cl-compiler@sail.stanford.edu

The question of efficiency of referencing a constant data structure
created with #, versus referencing a special variable has been raised.
I have never really studied an implementation of #, so I don't have
much of a feel for this.  Can any of you folks comment on what happens
in your implementation?  The person who raised the issue thought that #,
would be much faster, but my gut feeling is that it would be about the
same speed.

Also, I'm curious to know:  what does your reader return for #, and how
does the compiler recognize it when it's buried inside of a QUOTE form?

-Sandra
-------

∂21-Jun-88  0932	CL-Compiler-mailer 	re: uses of #, 
Received: from vaxa.isi.edu by SAIL.Stanford.EDU with TCP; 21 Jun 88  09:32:07 PDT
Posted-Date: Tue, 21 Jun 88 09:32:41 PDT
Message-Id: <8806211632.AA03841@vaxa.isi.edu>
Received: from LOCALHOST by vaxa.isi.edu (5.54/5.51)
	id AA03841; Tue, 21 Jun 88 09:32:45 PDT
To: CL-COMPILER@sail.stanford.edu
From: goldman@vaxa.isi.edu
Subject: re: uses of #,
Date: Tue, 21 Jun 88 09:32:41 PDT
Sender: goldman@vaxa.isi.edu

I believe that all our uses of #, would be subsumed by the following
construct, which we have implemented in various ways in each of 3
common lisp implementations, but believe cannot be implemented portably
within common lisp as it now stands:


UNVARYING   e							[Special Form]
e may be any expression.  The value of (UNVARYING e) is simply the (first)
value returned by e.  However, the programmer authorizes the implementation
to cache the value and return the cached result (or a value EQL to it) on
successive executions of the same occurrence of (UNVARYING e).
There is NO implication that the value may be computed at "compile" time,
although analysis of e may show that it is safe to do so under some
circumstances -- in particular, if e involves only constant subexpressions
and contstant, side-effect-free, stateless, functions and macros.



One implementation we have expands (UNVARYING e) into:

(let ((#:G0001 '(NIL . NIL)))
  (if (car #:G0001)
      (cdr #:G0001)
      (setf (car #:G0001) t (cdr #:G0001) e)))

[This implementation will not work, of course, on an implementation that
takes the position that a quoted CONS datum may not be smashed.]



We use this macro in many places where "#," cannot be used, because it
appears in the expansion of some other macro.  I believe that all the uses
we make of the "read-time" evaluating done by "#," could be replaced
acceptably by the "first execution time" evaluting done by UNVARYING.  

On the other hand, most of our uses of UNVARYING  COULD
be safely evaluated at "load" time, and would yield somewhat smoother
performance if evaluation were done then rather than at first execution
time.  So I'd like UNVARYING to have an optional parameter to specify
whether load-time evaluation is authorized, with the default being YES.
[Of course, this assumes that the concept of "load time", or "program
construction time", is considered to be sufficiently well defined that
language semantics can refer to it.]

The reason that compile-time evaluation won't work in most of these cases
is that it is not proper to "create" (i.e., cons)  the VALUE at 
load time, only to "find" it.  The expression e constitutes the
directions for finding the correct value.

∂21-Jun-88  1019	CL-Compiler-mailer 	#, implementation   
Received: from labrea.stanford.edu by SAIL.Stanford.EDU with TCP; 21 Jun 88  10:19:31 PDT
Received: by labrea.stanford.edu; Tue, 21 Jun 88 10:19:37 PDT
Received: from blacksox.lucid.com by edsel id AA20890g; Tue, 21 Jun 88 10:13:19 PDT
Received: by blacksox id AA00339g; Tue, 21 Jun 88 10:12:16 pdt
Date: Tue, 21 Jun 88 10:12:16 pdt
From: Eric Benson <edsel!eb@labrea.stanford.edu>
Message-Id: <8806211712.AA00339@blacksox.lucid.com>
To: sandra@cs.utah.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Sandra J Loosemore's message of Tue, 21 Jun 88 08:53:15 MDT <8806211453.AA15752@cs.utah.edu>
Subject: #, implementation

In our implementation, a reference to a constant data structure using
#, has one less memory indirection than a reference through a special
variable.  However, it has exactly the same overhead as a reference
through a lexical variable.  For example,

(defun something-funny ()
  (do-something-with '#,(make-some-data-structure)))

and

(let ((some-data-structure (make-some-data-structure)))
  (defun something-funny ()
    (do-something-with some-data-structure)))

have exactly the same overhead for the reference to the data
structure.  In

(defparameter *some-data-structure* (make-some-data-structure))

(defun something-funny ()
  (do-something-with *some-data-structure*))

there is one more memory indirection.

∂21-Jun-88  1031	CL-Compiler-mailer 	#, implementation   
Received: from labrea.stanford.edu by SAIL.Stanford.EDU with TCP; 21 Jun 88  10:31:22 PDT
Received: by labrea.stanford.edu; Tue, 21 Jun 88 10:31:34 PDT
Received: from blacksox.lucid.com by edsel id AA20943g; Tue, 21 Jun 88 10:24:39 PDT
Received: by blacksox id AA00343g; Tue, 21 Jun 88 10:23:40 pdt
Date: Tue, 21 Jun 88 10:23:40 pdt
From: Eric Benson <edsel!eb@labrea.stanford.edu>
Message-Id: <8806211723.AA00343@blacksox.lucid.com>
To: sandra@cs.utah.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Sandra J Loosemore's message of Tue, 21 Jun 88 08:53:15 MDT <8806211453.AA15752@cs.utah.edu>
Subject: #, implementation

   From: sandra@cs.utah.edu (Sandra J Loosemore)
   Date: Tue, 21 Jun 88 08:53:15 MDT

   Also, I'm curious to know:  what does your reader return for #, and how
   does the compiler recognize it when it's buried inside of a QUOTE form?

   -Sandra
   -------


Our reader returns an object of a certain internal type (defined by
DEFSTRUCT) containing the expression following the #, .  This is
recognized not by the compiler but by the "fasdumper," the function
that writes binary files.  When such an object is encountered while
traversing a constant data structure, the fasdumper emits a special
opcode which causes EVAL to be called at load time on the expression
contained in the object.

∂21-Jun-88  1717	CL-Compiler-mailer 	#, implementation   
Received: from EDDIE.MIT.EDU by SAIL.Stanford.EDU with TCP; 21 Jun 88  17:17:52 PDT
Received: by EDDIE.MIT.EDU with UUCP with smail2.5 with sendmail-5.45/4.7 id <AA17582@EDDIE.MIT.EDU>; Tue, 21 Jun 88 19:59:19 EDT
Received: by spt.entity.com (smail2.5); 21 Jun 88 19:45:57 EDT (Tue)
To: sandra@cs.utah.edu
Cc: cl-compiler@sail.stanford.edu
In-Reply-To: Sandra J Loosemore's message of Tue, 21 Jun 88 08:53:15 MDT <8806211453.AA15752@cs.utah.edu>
Subject: #, implementation
Message-Id: <8806211945.AA25667@spt.entity.com>
Date: 21 Jun 88 19:45:57 EDT (Tue)
From: gz@spt.entity.com (Gail Zacharias)

   From: sandra@cs.utah.edu (Sandra J Loosemore)
   Date: Tue, 21 Jun 88 08:53:15 MDT

    The question of efficiency of referencing a constant data structure
   created with #, versus referencing a special variable has been raised.

Depending on the setting of optimization options, we might do boundp checks on
compiled special variable references.  There is also the space inefficiency of
having to create a symbol (and a pname string, and a slot in a package, etc)
to hold a value which is only going to be referenced once.

   Also, I'm curious to know:  what does your reader return for #, and how
   does the compiler recognize it when it's buried inside of a QUOTE form?

We return a list whose car is a unique gensym and whose cadr is the form.
When it occurs inside a quoted form, it ends up passing unnoticed through the
compiler to the fasldumper, which then handles it specially.  In addition, the
gensym has a macro definition in an arguably pointless attempt to make
unquoted #,'s do something reasonable (or at least semantically correct)
whenever possible.  We don't handle the special-form case -- as in "(LET
#,(MY-VARS) ...)" -- at all (i.e. don't even signal an error in most cases).

∂01-Jul-88  1229	CL-Compiler-mailer 	status report  
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 1 Jul 88  12:27:31 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA02284; Fri, 1 Jul 88 13:27:18 MDT
From: sandra@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8807011927.AA02284@cs.utah.edu>
Date: Fri, 1 Jul 88 13:27:17 MDT
Subject: status report
To: cl-compiler@sail.stanford.edu


It seems like the mail on #, has died down, so I'm planning to start
working on a proposal on this issue over the weekend.  Actually, I'm
thinking of sketching out two or three alternate proposals and then
taking a poll on which one to pursue further.

On a personal note, I have resigned from my job at Evans & Sutherland
and am returning to being a full-time student at the UofU.  My departure
from E&S is happening a bit faster than I had planned; the other day a
water main broke and flooded the building I worked in -- there was 4
inches of muddy water in my office and over a foot in my lab in the
basement, totally trashing all the computer equipment down there.
Anyway, my e-mail address remains the same (sandra@cs.utah.edu) and I do
plan to continue participating in X3J13.

-Sandra
-------

∂03-Jul-88  1154	CL-Compiler-mailer 	Handling of #, (load-time-eval)    
Received: from cs.utah.edu by SAIL.Stanford.EDU with TCP; 3 Jul 88  11:54:27 PDT
Received: by cs.utah.edu (5.54/utah-2.0-cs)
	id AA02737; Sun, 3 Jul 88 12:54:18 MDT
Received: by cdr.utah.edu (5.54/utah-2.0-leaf)
	id AA18432; Sun, 3 Jul 88 12:54:15 MDT
From: sandra%cdr@cs.utah.edu (Sandra J Loosemore)
Message-Id: <8807031854.AA18432@cdr.utah.edu>
Date: Sun, 3 Jul 88 12:54:14 MDT
Subject: Handling of #, (load-time-eval)
To: cl-compiler@sail.stanford.edu

Here are the possible alternatives for dealing with #,.  The first two
have already been written up in detail in the LOAD-TIME-EVAL issue
from the cleanup committee.  I only have a paper copy of this issue;
could somebody (Dan?) who has an electronic copy please send it around
to the rest of us?

(1) (LOAD-TIME-EVAL:QUOTED-MAGIC-TOKEN) Define a function that returns
a magic token that can appear inside quoted structures to define a
load-time constant.

(2) (LOAD-TIME-EVAL:NEW-SPECIAL-FORM) Define a new special form that
causes its argument to be evaluated once at load time and the value
cached.  Calls to the special form would have to appear in a place
where they would be evaluated, and not inside quoted structure.  #, would
be changed incompatibly.

(3) Throw out #, entirely and do not provide any other similar
functionality.

(4) Simply clarify that #, must appear inside of quoted structure and
that it's really not the same as #. in interpreted code.

(5) Like (2), but somehow graft the new functionality onto EVAL-WHEN.

To summarize briefly the responses I got to my question about #,
usage, it appears that nearly all usages of #, could be replaced by
references to a variable initialized with DEFVAR or DEFCONSTANT.  The
people who responded appeared to be well aware of this, but liked #,
syntax better because they didn't have to think of a variable name,
and thought it might be somewhat more efficient.  As far as I can
tell, #, is almost never used at other than top-level in quoted
structure (that is, people use '#,(foo) but not '(... #',(foo) ...)).

What I would like to do is get some reactions to the various
alternatives so that I'll know which one(s) to pursue further.  I
personally would favor either (2) or (3), but if there isn't any
concensus arising on this issue I think we would have to write up (4)
as the fallback position.

Finally, a subissue I think we need to touch upon: Should the object
returned by evaluating the form indicated by #, be read-only?  I'd
argue that if we go with a proposal that restricts #, to appearing in
quoted structure, and if we accept that quoted structures are
read-only, we'd have to say Yes to this question as well.

-Sandra
-------

∂05-Jul-88  1202	CL-Compiler-mailer 	mailing list   
Received: from decwrl.dec.com by SAIL.Stanford.EDU with TCP; 5 Jul 88  12:01:57 PDT
Received: by decwrl.dec.com (5.54.4/4.7.34)
	id AA06621; Tue, 5 Jul 88 12:01:30 PDT
Message-Id: <8807051901.AA06621@decwrl.dec.com>
From: chapman%aitg.DEC@decwrl.dec.com
Date: 5 Jul 88 15:00
To: cl-compiler@sail.stanford.edu
Subject: mailing list

Could you please add me to the cl-compiler mailing list?

Thanks,
Kathy Chapman

∂06-Jul-88  0719	CL-Compiler-mailer 	Handling of #, (load-time-eval)    
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 6 Jul 88  07:19:06 PDT
Received: from franz.UUCP by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA03419; Wed, 6 Jul 88 07:18:30 PDT
Received: by franz (3.2/3.14)
	id AA26774; Wed, 6 Jul 88 07:11:16 PDT
Received: by feast (5.5/3.14)
	id AA00607; Wed, 6 Jul 88 09:57:28 EDT
Date: Wed, 6 Jul 88 09:57:28 EDT
From: franz!feast!smh@ucbarpa.Berkeley.EDU (Steven M. Haflich)
Message-Id: <8807061357.AA00607@feast>
To: franz!sail.stanford.edu!cl-compiler
In-Reply-To: Sandra J Loosemore's message of Sun, 3 Jul 88 12:54:14 MDT <8807031854.AA18432@cdr.utah.edu>
Subject: Handling of #, (load-time-eval)

   From: franz!ucbarpa!cs.utah.edu!sandra%cdr (Sandra J Loosemore)

   (3) Throw out #, entirely and do not provide any other similar
   functionality.

But, of course, all implementations would preserve it anyway for
backward compatibility.  This is a wishy-washy choice.

   (4) Simply clarify that #, must appear inside of quoted structure and
   that it's really not the same as #. in interpreted code.

A real problem with #, is that it's mechanism is unavailable *except*
via the reader, but some functions are composed by functions other
than the reader.

   To summarize briefly the responses I got to my question about #,
   usage, it appears that nearly all usages of #, could be replaced by
   references to a variable initialized with DEFVAR or DEFCONSTANT.  The
   people who responded appeared to be well aware of this, but liked #,
   syntax better because they didn't have to think of a variable name,
   and thought it might be somewhat more efficient.

I don't remember whether this was mentioned explicitly, but one
benefit of #, is that it is *clearer* -- the load-time-eval form
appears at its point of use or inclusion, and not at some distant
DEFVAR.  This is not a minor point.

   As far as I can
   tell, #, is almost never used at other than top-level in quoted
   structure (that is, people use '#,(foo) but not '(... #',(foo) ...)).

Allegro's flavor implementation does use the #, mechanism inside
quoted structures.  However, this is also a prime example of a program
that (almost) needs access to the magic internal token, since the
forms being compiled are generated by hairy DEFFLAVOR internal macros
and not read by the reader.

   Finally, a subissue I think we need to touch upon: Should the object
   returned by evaluating the form indicated by #, be read-only?  I'd
   argue that if we go with a proposal that restricts #, to appearing in
   quoted structure, and if we accept that quoted structures are
   read-only, we'd have to say Yes to this question as well.

I think that #, should only appear inside quoted structure.  However,
as an extension, might we also permit the value returned by #, to be
any self-evaluating object?  E.g.:

  (setq foo
     (1+ #,(seventh (decode-universal-time
                      (get-universal-time)))))

The value returned by the #, expression is always an integer, which is
always self-evaluating.  The compiler could be allowed to assume that
anything returned by #, will not require further evaluation.

∂07-Jul-88  0949	CL-Compiler-mailer 	Re:  Handling of #, (load-time-eval)    
Received: from Sun.COM by SAIL.Stanford.EDU with TCP; 7 Jul 88  09:49:49 PDT
Received: from snail.sun.com by Sun.COM (4.0/SMI-4.0)
	id AA22842; Thu, 7 Jul 88 09:48:07 PDT
Received: from clam.sun.com by snail.sun.com (4.0/SMI-3.2)
	id AA16100; Thu, 7 Jul 88 09:43:27 PDT
Received: by clam.sun.com (3.2/SMI-3.2)
	id AA19882; Thu, 7 Jul 88 09:51:00 PDT
Date: Thu, 7 Jul 88 09:51:00 PDT
From: cperdue@Sun.COM (Cris Perdue)
Message-Id: <8807071651.AA19882@clam.sun.com>
To: cl-compiler@sail.stanford.edu, sandra%cdr@cs.utah.edu
Subject: Re:  Handling of #, (load-time-eval)

My preferences, in order, are:

Alternative (3) Throw out #, entirely.

Alternative (2) Define a new special form.

Note that in CLtL, p. 86, (QUOTE x) is defined as "simply returns x.
The object is not evaluated and may be any Lisp object whatsoever.
This construct allows any Lisp object to be written as a constant value
in a program."

I would prefer to see the simplicity of QUOTE retained rather than
complicating it to support #,.

I prefer removal of #, from the language because it is logically
impossible for it to be as described in CLtL -- just a read macro --
and even if made a self-consistent part of the language it requires
a special mechanism unique to it.  Since there are alternatives to
it, I would omit it.

It seems appropriate to me that if QUOTEd constants are permitted to
be read-only, values produced by #, would also be permitted to be
read-only.  In other words, it would be an error to attempt to modify them.

				-Cris

∂08-Jul-88  0919	CL-Compiler-mailer 	Handling of #, (load-time-eval)    
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 8 Jul 88  09:19:06 PDT
Received: from franz.UUCP by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA00573; Fri, 8 Jul 88 09:18:16 PDT
Received: by franz (3.2/3.14)
	id AA01885; Fri, 8 Jul 88 08:36:16 PDT
Received: by feast (5.5/3.14)
	id AA00581; Fri, 8 Jul 88 02:51:44 EDT
Date: Fri, 8 Jul 88 02:51:44 EDT
From: franz!feast!smh@ucbarpa.Berkeley.EDU (Steven M. Haflich)
Message-Id: <8807080651.AA00581@feast>
To: franz!sail.stanford.edu!cl-compiler
In-Reply-To: Sandra J Loosemore's message of Wed, 6 Jul 88 17:39:01 MDT <8807062339.AA20085@cdr.utah.edu>
Subject: Handling of #, (load-time-eval)

   From: franz!ucbarpa!cs.utah.edu!sandra%cdr (Sandra J Loosemore)

   I interpret your reply to mean that you would support some variant of
   the quoted magic token proposal, right? 

Yes, but failing that I would also accept dropping it from the
language entirely if no magic cookie proposal appears sufficiently
clean.  My rational for wanting to make at least a sincere effort to
salvage it is that no one feels *very* strongly either way about
dropping it, but if it can be defined cleanly, it is a useful (if not
essential) tool for some purposes.

∂08-Jul-88  0919	CL-Compiler-mailer 	Handling of #, (load-time-eval)    
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 8 Jul 88  09:19:10 PDT
Received: from franz.UUCP by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA00576; Fri, 8 Jul 88 09:18:19 PDT
Received: by franz (3.2/3.14)
	id AA01892; Fri, 8 Jul 88 08:36:28 PDT
Received: by feast (5.5/3.14)
	id AA00769; Fri, 8 Jul 88 11:21:18 EDT
Date: Fri, 8 Jul 88 11:21:18 EDT
From: franz!feast!smh@ucbarpa.Berkeley.EDU (Steven M. Haflich)
Message-Id: <8807081521.AA00769@feast>
To: franz!sail.stanford.edu!cl-compiler
In-Reply-To: Cris Perdue's message of Thu, 7 Jul 88 09:51:00 PDT <8807071651.AA19882@clam.sun.com>
Subject:  Handling of #, (load-time-eval)

   From: franz!ucbarpa!Sun.COM!cperdue (Cris Perdue)

   Note that in CLtL, p. 86, (QUOTE x) is defined as "simply returns x.
   The object is not evaluated and may be any Lisp object whatsoever.
   This construct allows any Lisp object to be written as a constant value
   in a program."

   I would prefer to see the simplicity of QUOTE retained rather than
   complicating it to support #,.

This "simple" description of QUOTE, I think, is not intended to cover
it's the effect of quoted objects during the fasl/load cycle.  There
are obvious examples of quoted objects that can't (in all
implementations) be written to a compiled file as a constant in a
program and reloaded.  PATHNAMEs and STREAMs are obvious examples.
Some implementations permit PATHNAMEs, but others cannot.  Some
implementations allow STREAMs to be written, but the STREAM is
magically closed or otherwise invalidated by load.

#, also has to do with the loading of compiled files, so this argument
based on the `simpleness' of QUOTE seems invalid.

   It seems appropriate to me that if QUOTEd constants are permitted to
   be read-only, values produced by #, would also be permitted to be
   read-only.  In other words, it would be an error to attempt to modify them.

I think it is not only reasonable but necessary to require that a #,
expression may only appear as a quoted object or inside a quoted
object.  This is almost the same as saying that #, may not be used
anywhere it could potentially be evaluated, or inside a declaration.

There might be a few warts, left like documentation strings.  The
following is clearly not legal! :-)

  (defun frobus (x)
    #,(progn (format *query-io*
               "Please enter documentation for FROBUS:")
             (read-line *query-io*))
    ...)

It would, however, be legal and perhaps plausible to use #. there.

∂08-Jul-88  1322	CL-Compiler-mailer 	Re:  Handling of #, (load-time-eval)    
Received: from ucbarpa.Berkeley.EDU by SAIL.Stanford.EDU with TCP; 8 Jul 88  13:22:10 PDT
Received: from franz.UUCP by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA04331; Fri, 8 Jul 88 13:21:20 PDT
Received: by franz (3.2/3.14)
	id AA02486; Fri, 8 Jul 88 12:18:56 PDT
Received: from SUN.COM by ucbarpa.Berkeley.EDU (5.59/1.28)
	id AA03167; Fri, 8 Jul 88 12:04:31 PDT
Received: from snail.sun.com by Sun.COM (4.0/SMI-4.0)
	id AA14178; Fri, 8 Jul 88 12:03:26 PDT
Received: from clam.sun.com by snail.sun.com (4.0/SMI-3.2)
	id AA21821; Fri, 8 Jul 88 11:58:43 PDT
Received: by clam.sun.com (3.2/SMI-3.2)
	id AA20816; Fri, 8 Jul 88 12:06:19 PDT
Date: Fri, 8 Jul 88 12:06:19 PDT
From: franz!ucbarpa!Sun.COM!cperdue@ucbarpa.Berkeley.EDU (Cris Perdue)
Message-Id: <8807081906.AA20816@clam.sun.com>
To: franz!feast!smh, franz!sail.stanford.edu!cl-compiler
Subject: Re:  Handling of #, (load-time-eval)

>    It seems appropriate to me that if QUOTEd constants are permitted to
>    be read-only, values produced by #, would also be permitted to be
>    read-only.  In other words, it would be an error to attempt to modify them.
> 
> I think it is not only reasonable but necessary to require that a #,
> expression may only appear as a quoted object or inside a quoted
> object.  This is almost the same as saying that #, may not be used
> anywhere it could potentially be evaluated, or inside a declaration.

Steve, I missed the connection between my comment and your comment here.
Also I'm not sure what you mean about #, not being useable anywhere it
could potentially be evaluated, or inside a declaration.  I see no
reason not to allow code such as (eval '#,(what-to-eval)) if we are
to allow #, at all.

When I talk about permitting #, or its magic cookie *only inside
quoted expressions*, I mean that this situation would be required
to exist after all macro expansion.

∂08-Jul-88  1532	CL-Compiler-mailer 	Handling of #, (load-time-eval)    
Received: from STONY-BROOK.SCRC.Symbolics.COM (SCRC-STONY-BROOK.ARPA) by SAIL.Stanford.EDU with TCP; 8 Jul 88  15:32:41 PDT
Received: from PEWEE.SCRC.Symbolics.COM by STONY-BROOK.SCRC.Symbolics.COM via CHAOS with CHAOS-MAIL id 430781; Fri 8-Jul-88 18:32:27 EDT
Date: Fri, 8 Jul 88 18:32 EDT
From: Kent M Pitman <KMP@STONY-BROOK.SCRC.Symbolics.COM>
Subject: Handling of #, (load-time-eval)
To: CL-Compiler@SAIL.Stanford.EDU
Message-ID: <880708183214.4.KMP@PEWEE.SCRC.Symbolics.COM>

I'm just on my way out the door so don't have time to go into it in
detail right now, but I've been feeling guilty about not making my
position on this be heard. I'll try to write up justifications for
the following positions when I have a bit of time (maybe next week)
but just so you know...

 - I feel strongly that #, is a minimal level of functionality
   necessary in CL. It would be well to specify whether it is
   intended to work either inside of QUOTE or outside, but it must
   be there in some form.

 - I do not feel that there is anything strange or low-level about
   #, . It expresses an abstract concept which is very high-level
   and fundamentally important to certain kinds of programming.

 - I think a special form such as the LOAD-TIME-CONSTANT form I
   proposed on CL-Cleanup a while back would be an important addition.
   I have seen no technical justification for not just providing it.
   It looks to me like you guys are getting overly ambitious and trying
   to define #, in terms of a revised EVAL-WHEN. [EVAL-WHEN is not
   trivially fixable, but even it serves a purpose and should be left
   alone if no suitable improvement can be devised. In any case,
   no matter what you think of EVAL-WHEN, I would ask you to not let
   those feelings keep you from making a good #, and/or 
   LOAD-TIME-CONSTANT form.]

 - There are numerous important uses of #, and LOAD-TIME-CONSTANT.
   CLOS is one use. The Fortran-To-Lisp translator which I wrote
   as an undergrad was another. Anything that involves `linking'
   requires this.

 - It is not adequate to say that this can be handled
   by closures and/or special variables because the code modularity
   may be inappropriate for closures, and the naming of special
   variables (if not also the size of all those wasted symbols!)
   would be prohibitive. Consider, for example, that my Fortran-To-Lisp
   translator used a Maclisp SQUID expression (the #, analog for
   Maclisp) on -every- translated variable reference. That is,
   A(A+3) in Fortran program FOO translated to
   (AREF *FORTRAN-MEMORY*
         (+ #,(+ (GET-PROGRAM-OFFSET "FOO") 
	         37) ;For example, program-relative offset of REAL A(10)
		     ; known at compile time
	    (AREF *FORTRAN-MEMORY*
		  #,(+ (GET-PROGRAM-OFFSET "FOO")
		       47) ;eg, program-relative offset of B
	    3)))
   Surely you don't expect me to make a closure for every one of these
   values. Surely you don't expect me to give every one of these values
   a name via DEFCONSTANT. How would I do that? Even if I did, I'd need
   a ``Pratt Stack'' (ask a Maclisp implementor) since the macro would
   have to be generating prerequisite DEFCONSTANT definitions on the fly.

 - Even if I could use closure references, they compile too slowly in every
   implementation I know of. QUOTE is generally just one move. A closure
   reference invariably has to indirect through some environment pointer.

 - I definitely need the capability of creating this kind of constant
   without guaranteeing that it will not be modified. I just did a flavors
   implementation and having this object be write-protected or copied at
   will was enough to screw my ability to use this. I sent detailed mail
   to Common-lisp about this but will send more mail later to this list
   because it looks to me like people aren't seeing the importance of this.
   It comes down to the fact, though, that I needed to implement instance
   variables by:
	(AREF #,(SOME-ARRAY) n)
   where the (SOME-ARRAY) might return an array that would need to be 
   ADJUST-ARRAY'd later without losing EQ-ness so that updates to the
   ADJUST-ARRAY'd version were seen by the array that (SOME-ARRAY) returned.

That's all I have time for right now. I hope this info is of use to you.